From 191ff327c49796e8a64fae893520d878b32d3268 Mon Sep 17 00:00:00 2001 From: Clément Pit--Claudel Date: Sun, 7 Jun 2015 12:38:31 -0700 Subject: Fix the UseBaseNameForFileName flag; it shouldn't set the return code to zero. The test suite relies on error codes all being zero (except for preprocessing errors), so add a flag for that (as suggested in a source comment). --- Source/DafnyDriver/DafnyDriver.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'Source/DafnyDriver/DafnyDriver.cs') diff --git a/Source/DafnyDriver/DafnyDriver.cs b/Source/DafnyDriver/DafnyDriver.cs index 854269c1..a769b829 100644 --- a/Source/DafnyDriver/DafnyDriver.cs +++ b/Source/DafnyDriver/DafnyDriver.cs @@ -104,9 +104,8 @@ namespace Microsoft.Dafny Console.WriteLine("Press Enter to exit."); Console.ReadLine(); } - if (CommandLineOptions.Clo.UseBaseNameForFileName && exitValue != ExitValue.PREPROCESSING_ERROR) + if (!DafnyOptions.O.CountVerificationErrors && exitValue != ExitValue.PREPROCESSING_ERROR) { - // TODO(wuestholz): We should probably add a separate flag for this. This is currently only used by the new testing infrastructure. return 0; } //Console.ReadKey(); -- cgit v1.2.3 From a297fb4b9e6c0b915b5bb5bd85050b26a9ed7e3b Mon Sep 17 00:00:00 2001 From: Michael Lowell Roberts Date: Fri, 12 Jun 2015 11:12:35 -0700 Subject: added -optimize option to compiler. --- Binaries/DafnyRuntime.cs | 506 +++++++++++++++++++++++++++++++---- Source/Dafny/DafnyOptions.cs | 12 + Source/DafnyDriver/DafnyDriver.cs | 13 +- Test/irondafny0/optimize0.dfy | 6 + Test/irondafny0/optimize0.dfy.expect | 6 + 5 files changed, 485 insertions(+), 58 deletions(-) create mode 100644 Test/irondafny0/optimize0.dfy create mode 100644 Test/irondafny0/optimize0.dfy.expect (limited to 'Source/DafnyDriver/DafnyDriver.cs') diff --git a/Binaries/DafnyRuntime.cs b/Binaries/DafnyRuntime.cs index fd680a0b..7d3799d8 100644 --- a/Binaries/DafnyRuntime.cs +++ b/Binaries/DafnyRuntime.cs @@ -4,39 +4,430 @@ using System.Numerics; namespace Dafny { using System.Collections.Generic; +// set this option if you want to use System.Collections.Immutable and if you know what you're doing. +#if DAFNY_USE_SYSTEM_COLLECTIONS_IMMUTABLE + using System.Collections.Immutable; + using System.Linq; public class Set { - Dictionary dict; - Set(Dictionary d) { + readonly ImmutableHashSet setImpl; + Set(ImmutableHashSet d) { + this.setImpl = d; + } + public static readonly Set Empty = new Set(ImmutableHashSet.Empty); + public static Set FromElements(params T[] values) { + return FromElements((IEnumerable)values); + } + public static Set FromElements(IEnumerable values) { + var d = ImmutableHashSet.Empty.ToBuilder(); + foreach (T t in values) + d.Add(t); + return new Set(d.ToImmutable()); + } + public static Set FromCollection(ICollection values) { + var d = ImmutableHashSet.Empty.ToBuilder(); + foreach (T t in values) + d.Add(t); + return new Set(d.ToImmutable()); + } + public int Length { + get { return this.setImpl.Count; } + } + public long LongLength { + get { return this.setImpl.Count; } + } + public IEnumerable Elements { + get { + return this.setImpl; + } + } + /// + /// This is an inefficient iterator for producing all subsets of "this". Each set returned is the same + /// Set object (but this Set object is fresh; in particular, it is not "this"). + /// + public IEnumerable> AllSubsets { + get { + // Start by putting all set elements into a list + var elmts = new List(); + elmts.AddRange(this.setImpl); + var n = elmts.Count; + var which = new bool[n]; + var s = ImmutableHashSet.Empty.ToBuilder(); + while (true) { + yield return new Set(s.ToImmutable()); + // "add 1" to "which", as if doing a carry chain. For every digit changed, change the membership of the corresponding element in "s". + int i = 0; + for (; i < n && which[i]; i++) { + which[i] = false; + s.Remove(elmts[i]); + } + if (i == n) { + // we have cycled through all the subsets + break; + } + which[i] = true; + s.Add(elmts[i]); + } + } + } + public bool Equals(Set other) { + return this.setImpl.Equals(other.setImpl); + } + public override bool Equals(object other) { + var otherSet = other as Set; + return otherSet != null && Equals(otherSet); + } + public override int GetHashCode() { + var hashCode = 1; + foreach (var t in this.setImpl) { + hashCode = hashCode * (t.GetHashCode()+3); + } + return hashCode; + } + public override string ToString() { + var s = "{"; + var sep = ""; + foreach (var t in this.setImpl) { + s += sep + t.ToString(); + sep = ", "; + } + return s + "}"; + } + public bool IsProperSubsetOf(Set other) { + return IsProperSubsetOf(other); + } + public bool IsSubsetOf(Set other) { + return IsSubsetOf(other); + } + public bool IsSupersetOf(Set other) { + return other.IsSupersetOf(this); + } + public bool IsProperSupersetOf(Set other) { + return other.IsProperSupersetOf(this); + } + public bool IsDisjointFrom(Set other) { + ImmutableHashSet a, b; + if (this.setImpl.Count < other.setImpl.Count) { + a = this.setImpl; b = other.setImpl; + } else { + a = other.setImpl; b = this.setImpl; + } + foreach (T t in a) { + if (b.Contains(t)) + return false; + } + return true; + } + public bool Contains(T t) { + return this.setImpl.Contains(t); + } + public Set Union(Set other) { + return new Set(this.setImpl.Union(other.setImpl)); + } + public Set Intersect(Set other) { + return new Set(this.setImpl.Intersect(other.setImpl)); + } + public Set Difference(Set other) { + return new Set(this.setImpl.Except(other.setImpl)); + } + } + public partial class MultiSet + { + + readonly ImmutableDictionary dict; + MultiSet(ImmutableDictionary d) { dict = d; } + public static readonly MultiSet Empty = new MultiSet(ImmutableDictionary.Empty); + public static MultiSet FromElements(params T[] values) { + var d = ImmutableDictionary.Empty.ToBuilder(); + foreach (T t in values) { + var i = 0; + if (!d.TryGetValue(t, out i)) { + i = 0; + } + d[t] = i + 1; + } + return new MultiSet(d.ToImmutable()); + } + public static MultiSet FromCollection(ICollection values) { + var d = ImmutableDictionary.Empty.ToBuilder(); + foreach (T t in values) { + var i = 0; + if (!d.TryGetValue(t, out i)) { + i = 0; + } + d[t] = i + 1; + } + return new MultiSet(d.ToImmutable()); + } + public static MultiSet FromSeq(Sequence values) { + var d = ImmutableDictionary.Empty.ToBuilder(); + foreach (T t in values.Elements) { + var i = 0; + if (!d.TryGetValue(t, out i)) { + i = 0; + } + d[t] = i + 1; + } + return new MultiSet(d.ToImmutable()); + } + public static MultiSet FromSet(Set values) { + var d = ImmutableDictionary.Empty.ToBuilder(); + foreach (T t in values.Elements) { + d[t] = 1; + } + return new MultiSet(d.ToImmutable()); + } + + public bool Equals(MultiSet other) { + return other.IsSubsetOf(this) && this.IsSubsetOf(other); + } + public override bool Equals(object other) { + return other is MultiSet && Equals((MultiSet)other); + } + public override int GetHashCode() { + var hashCode = 1; + foreach (var kv in dict) { + var key = kv.Key.GetHashCode(); + key = (key << 3) | (key >> 29) ^ kv.Value.GetHashCode(); + hashCode = hashCode * (key + 3); + } + return hashCode; + } + public override string ToString() { + var s = "multiset{"; + var sep = ""; + foreach (var kv in dict) { + var t = kv.Key.ToString(); + for (int i = 0; i < kv.Value; i++) { + s += sep + t.ToString(); + sep = ", "; + } + } + return s + "}"; + } + public bool IsProperSubsetOf(MultiSet other) { + return !Equals(other) && IsSubsetOf(other); + } + public bool IsSubsetOf(MultiSet other) { + foreach (T t in dict.Keys) { + if (!other.dict.ContainsKey(t) || other.dict[t] < dict[t]) + return false; + } + return true; + } + public bool IsSupersetOf(MultiSet other) { + return other.IsSubsetOf(this); + } + public bool IsProperSupersetOf(MultiSet other) { + return other.IsProperSubsetOf(this); + } + public bool IsDisjointFrom(MultiSet other) { + foreach (T t in dict.Keys) { + if (other.dict.ContainsKey(t)) + return false; + } + foreach (T t in other.dict.Keys) { + if (dict.ContainsKey(t)) + return false; + } + return true; + } + public bool Contains(T t) { + return dict.ContainsKey(t); + } + public MultiSet Union(MultiSet other) { + if (dict.Count == 0) + return other; + else if (other.dict.Count == 0) + return this; + var r = ImmutableDictionary.Empty.ToBuilder(); + foreach (T t in dict.Keys) { + var i = 0; + if (!r.TryGetValue(t, out i)) { + i = 0; + } + r[t] = i + dict[t]; + } + foreach (T t in other.dict.Keys) { + var i = 0; + if (!r.TryGetValue(t, out i)) { + i = 0; + } + r[t] = i + other.dict[t]; + } + return new MultiSet(r.ToImmutable()); + } + public MultiSet Intersect(MultiSet other) { + if (dict.Count == 0) + return this; + else if (other.dict.Count == 0) + return other; + var r = ImmutableDictionary.Empty.ToBuilder(); + foreach (T t in dict.Keys) { + if (other.dict.ContainsKey(t)) { + r[t] = other.dict[t] < dict[t] ? other.dict[t] : dict[t]; + } + } + return new MultiSet(r.ToImmutable()); + } + public MultiSet Difference(MultiSet other) { // \result == this - other + if (dict.Count == 0) + return this; + else if (other.dict.Count == 0) + return this; + var r = ImmutableDictionary.Empty.ToBuilder(); + foreach (T t in dict.Keys) { + if (!other.dict.ContainsKey(t)) { + r[t] = dict[t]; + } else if (other.dict[t] < dict[t]) { + r[t] = dict[t] - other.dict[t]; + } + } + return new MultiSet(r.ToImmutable()); + } + public IEnumerable Elements { + get { + foreach (T t in dict.Keys) { + int n; + dict.TryGetValue(t, out n); + for (int i = 0; i < n; i ++) { + yield return t; + } + } + } + } + } + + public partial class Map + { + readonly ImmutableDictionary dict; + Map(ImmutableDictionary d) { + dict = d; + } + public static readonly Map Empty = new Map(ImmutableDictionary.Empty); + public static Map FromElements(params Pair[] values) { + var d = ImmutableDictionary.Empty.ToBuilder(); + foreach (Pair p in values) { + d[p.Car] = p.Cdr; + } + return new Map(d.ToImmutable()); + } + public static Map FromCollection(List> values) { + var d = ImmutableDictionary.Empty.ToBuilder(); + foreach (Pair p in values) { + d[p.Car] = p.Cdr; + } + return new Map(d.ToImmutable()); + } + public int Length { + get { return dict.Count; } + } + public long LongLength { + get { return dict.Count; } + } + public bool Equals(Map other) { + foreach (U u in dict.Keys) { + V v1, v2; + if (!dict.TryGetValue(u, out v1)) { + return false; // this shouldn't happen + } + if (!other.dict.TryGetValue(u, out v2)) { + return false; // other dictionary does not contain this element + } + if (!v1.Equals(v2)) { + return false; + } + } + foreach (U u in other.dict.Keys) { + if (!dict.ContainsKey(u)) { + return false; // this shouldn't happen + } + } + return true; + } + public override bool Equals(object other) { + return other is Map && Equals((Map)other); + } + public override int GetHashCode() { + var hashCode = 1; + foreach (var kv in dict) { + var key = kv.Key.GetHashCode(); + key = (key << 3) | (key >> 29) ^ kv.Value.GetHashCode(); + hashCode = hashCode * (key + 3); + } + return hashCode; + } + public override string ToString() { + var s = "map["; + var sep = ""; + foreach (var kv in dict) { + s += sep + kv.Key.ToString() + " := " + kv.Value.ToString(); + sep = ", "; + } + return s + "]"; + } + public bool IsDisjointFrom(Map other) { + foreach (U u in dict.Keys) { + if (other.dict.ContainsKey(u)) + return false; + } + foreach (U u in other.dict.Keys) { + if (dict.ContainsKey(u)) + return false; + } + return true; + } + public bool Contains(U u) { + return dict.ContainsKey(u); + } + public V Select(U index) { + return dict[index]; + } + public Map Update(U index, V val) { + return new Map(dict.SetItem(index, val)); + } + public IEnumerable Domain { + get { + return dict.Keys; + } + } + } +#else // !def DAFNY_USE_SYSTEM_COLLECTIONS_IMMUTABLE + public class Set + { + HashSet set; + Set(HashSet s) { + this.set = s; + } public static Set Empty { get { - return new Set(new Dictionary(0)); + return new Set(new HashSet()); } } public static Set FromElements(params T[] values) { - Dictionary d = new Dictionary(values.Length); + var s = new HashSet(); foreach (T t in values) - d[t] = true; - return new Set(d); + s.Add(t); + return new Set(s); } public static Set FromCollection(ICollection values) { - Dictionary d = new Dictionary(); + HashSet s = new HashSet(); foreach (T t in values) - d[t] = true; - return new Set(d); + s.Add(t); + return new Set(s); } public int Length { - get { return dict.Count; } + get { return this.set.Count; } } public long LongLength { - get { return dict.Count; } + get { return this.set.Count; } } public IEnumerable Elements { get { - return dict.Keys; + return this.set; } } /// @@ -47,36 +438,36 @@ namespace Dafny get { // Start by putting all set elements into a list var elmts = new List(); - elmts.AddRange(dict.Keys); + elmts.AddRange(this.set); var n = elmts.Count; var which = new bool[n]; - var s = new Set(new Dictionary(0)); + var s = new Set(new HashSet()); while (true) { yield return s; // "add 1" to "which", as if doing a carry chain. For every digit changed, change the membership of the corresponding element in "s". int i = 0; for (; i < n && which[i]; i++) { which[i] = false; - s.dict.Remove(elmts[i]); + s.set.Remove(elmts[i]); } if (i == n) { // we have cycled through all the subsets break; } which[i] = true; - s.dict.Add(elmts[i], true); + s.set.Add(elmts[i]); } } } public bool Equals(Set other) { - return dict.Count == other.dict.Count && IsSubsetOf(other); + return this.set.Count == other.set.Count && IsSubsetOf(other); } public override bool Equals(object other) { return other is Set && Equals((Set)other); } public override int GetHashCode() { var hashCode = 1; - foreach (var t in dict.Keys) { + foreach (var t in this.set) { hashCode = hashCode * (t.GetHashCode()+3); } return hashCode; @@ -84,20 +475,20 @@ namespace Dafny public override string ToString() { var s = "{"; var sep = ""; - foreach (var t in dict.Keys) { + foreach (var t in this.set) { s += sep + t.ToString(); sep = ", "; } return s + "}"; } public bool IsProperSubsetOf(Set other) { - return dict.Count < other.dict.Count && IsSubsetOf(other); + return this.set.Count < other.set.Count && IsSubsetOf(other); } public bool IsSubsetOf(Set other) { - if (other.dict.Count < dict.Count) + if (other.set.Count < this.set.Count) return false; - foreach (T t in dict.Keys) { - if (!other.dict.ContainsKey(t)) + foreach (T t in this.set) { + if (!other.set.Contains(t)) return false; } return true; @@ -109,66 +500,66 @@ namespace Dafny return other.IsProperSubsetOf(this); } public bool IsDisjointFrom(Set other) { - Dictionary a, b; - if (dict.Count < other.dict.Count) { - a = dict; b = other.dict; + HashSet a, b; + if (this.set.Count < other.set.Count) { + a = this.set; b = other.set; } else { - a = other.dict; b = dict; + a = other.set; b = this.set; } - foreach (T t in a.Keys) { - if (b.ContainsKey(t)) + foreach (T t in a) { + if (b.Contains(t)) return false; } return true; } public bool Contains(T t) { - return dict.ContainsKey(t); + return this.set.Contains(t); } public Set Union(Set other) { - if (dict.Count == 0) + if (this.set.Count == 0) return other; - else if (other.dict.Count == 0) + else if (other.set.Count == 0) return this; - Dictionary a, b; - if (dict.Count < other.dict.Count) { - a = dict; b = other.dict; + HashSet a, b; + if (this.set.Count < other.set.Count) { + a = this.set; b = other.set; } else { - a = other.dict; b = dict; + a = other.set; b = this.set; } - Dictionary r = new Dictionary(); - foreach (T t in b.Keys) - r[t] = true; - foreach (T t in a.Keys) - r[t] = true; + var r = new HashSet(); + foreach (T t in b) + r.Add(t); + foreach (T t in a) + r.Add(t); return new Set(r); } public Set Intersect(Set other) { - if (dict.Count == 0) + if (this.set.Count == 0) return this; - else if (other.dict.Count == 0) + else if (other.set.Count == 0) return other; - Dictionary a, b; - if (dict.Count < other.dict.Count) { - a = dict; b = other.dict; + HashSet a, b; + if (this.set.Count < other.set.Count) { + a = this.set; b = other.set; } else { - a = other.dict; b = dict; + a = other.set; b = this.set; } - var r = new Dictionary(); - foreach (T t in a.Keys) { - if (b.ContainsKey(t)) - r.Add(t, true); + var r = new HashSet(); + foreach (T t in a) { + if (b.Contains(t)) + r.Add(t); } return new Set(r); } public Set Difference(Set other) { - if (dict.Count == 0) + if (this.set.Count == 0) return this; - else if (other.dict.Count == 0) + else if (other.set.Count == 0) return this; - var r = new Dictionary(); - foreach (T t in dict.Keys) { - if (!other.dict.ContainsKey(t)) - r.Add(t, true); + var r = new HashSet(); + foreach (T t in this.set) { + if (!other.set.Contains(t)) + r.Add(t); } return new Set(r); } @@ -447,6 +838,7 @@ namespace Dafny } } } +#endif public class Sequence { T[] elmts; diff --git a/Source/Dafny/DafnyOptions.cs b/Source/Dafny/DafnyOptions.cs index a6827d5f..125ab11e 100644 --- a/Source/Dafny/DafnyOptions.cs +++ b/Source/Dafny/DafnyOptions.cs @@ -55,6 +55,7 @@ namespace Microsoft.Dafny public bool ignoreAutoReq = false; public bool AllowGlobals = false; public bool CountVerificationErrors = true; + public bool Optimize = false; protected override bool ParseOption(string name, Bpl.CommandLineOptionEngine.CommandLineParseState ps) { var args = ps.args; // convenient synonym @@ -180,6 +181,11 @@ namespace Microsoft.Dafny return true; } + case "optimize": { + Optimize = true; + return true; + } + default: break; } @@ -270,6 +276,12 @@ namespace Microsoft.Dafny of verification errors. 1 (default) - If preprocessing succeeds, set exit code to the number of verification errors. + /optimize Produce optimized C# code, meaning: + - selects optimized C# prelude by passing + /define:DAFNY_USE_SYSTEM_COLLECTIONS_IMMUTABLE to csc.exe (requires + System.Collections.Immutable.dll in the source directory to successfully + compile). + - passes /optimize flag to csc.exe. "); base.Usage(); // also print the Boogie options } diff --git a/Source/DafnyDriver/DafnyDriver.cs b/Source/DafnyDriver/DafnyDriver.cs index a769b829..cf464754 100644 --- a/Source/DafnyDriver/DafnyDriver.cs +++ b/Source/DafnyDriver/DafnyDriver.cs @@ -15,6 +15,8 @@ namespace Microsoft.Dafny using System.Collections.Generic; using System.Diagnostics.Contracts; using System.IO; + using System.Reflection; + using Microsoft.Boogie; using Bpl = Microsoft.Boogie; @@ -330,7 +332,7 @@ namespace Microsoft.Dafny } else { - var provider = CodeDomProvider.CreateProvider("CSharp"); + var provider = CodeDomProvider.CreateProvider("CSharp", new Dictionary { { "CompilerVersion", "v4.0" } }); var cp = new System.CodeDom.Compiler.CompilerParameters(); cp.GenerateExecutable = hasMain; if (DafnyOptions.O.RunAfterCompile) { @@ -344,6 +346,15 @@ namespace Microsoft.Dafny } 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"); + + if (DafnyOptions.O.Optimize) { + var libPath = Path.GetDirectoryName(dafnyProgramName); + cp.CompilerOptions += string.Format(" /optimize /define:DAFNY_USE_SYSTEM_COLLECTIONS_IMMUTABLE /lib:{0}", libPath); + cp.ReferencedAssemblies.Add("System.Collections.Immutable.dll"); + cp.ReferencedAssemblies.Add("System.Runtime.dll"); + } var cr = provider.CompileAssemblyFromSource(cp, csharpProgram); var assemblyName = Path.GetFileName(cr.PathToAssembly); diff --git a/Test/irondafny0/optimize0.dfy b/Test/irondafny0/optimize0.dfy new file mode 100644 index 00000000..865d8707 --- /dev/null +++ b/Test/irondafny0/optimize0.dfy @@ -0,0 +1,6 @@ +// RUN: %dafny /compile:3 /optimize /print:"%t.print" /dprint:"%t.dprint" "%s" > "%t" +// RUN: %diff "%s.expect" "%t" + +method Main() { + print "o hai!"; +} diff --git a/Test/irondafny0/optimize0.dfy.expect b/Test/irondafny0/optimize0.dfy.expect new file mode 100644 index 00000000..6b3e13c5 --- /dev/null +++ b/Test/irondafny0/optimize0.dfy.expect @@ -0,0 +1,6 @@ + +Dafny program verifier finished with 2 verified, 0 errors +Program compiled successfully +Running... + +o hai! \ No newline at end of file -- cgit v1.2.3 From 379f88f77fbb86a4be9eac6825c7a9c1aabb2316 Mon Sep 17 00:00:00 2001 From: Michael Lowell Roberts Date: Tue, 16 Jun 2015 15:02:55 -0700 Subject: System.Collections.Immutable.dll is now stored in the Binaries directory and copied to the output directory when the /optimize flag is used. --- Binaries/System.Collections.Immutable.dll | Bin 0 -> 149752 bytes Source/DafnyDriver/DafnyDriver.cs | 18 +++++++++++++++--- 2 files changed, 15 insertions(+), 3 deletions(-) create mode 100644 Binaries/System.Collections.Immutable.dll (limited to 'Source/DafnyDriver/DafnyDriver.cs') diff --git a/Binaries/System.Collections.Immutable.dll b/Binaries/System.Collections.Immutable.dll new file mode 100644 index 00000000..bcf23fe5 Binary files /dev/null and b/Binaries/System.Collections.Immutable.dll differ diff --git a/Source/DafnyDriver/DafnyDriver.cs b/Source/DafnyDriver/DafnyDriver.cs index cf464754..ce4d726f 100644 --- a/Source/DafnyDriver/DafnyDriver.cs +++ b/Source/DafnyDriver/DafnyDriver.cs @@ -349,10 +349,13 @@ namespace Microsoft.Dafny 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) { - var libPath = Path.GetDirectoryName(dafnyProgramName); - cp.CompilerOptions += string.Format(" /optimize /define:DAFNY_USE_SYSTEM_COLLECTIONS_IMMUTABLE /lib:{0}", libPath); - cp.ReferencedAssemblies.Add("System.Collections.Immutable.dll"); + cp.CompilerOptions += " /optimize /define:DAFNY_USE_SYSTEM_COLLECTIONS_IMMUTABLE"; + cp.ReferencedAssemblies.Add(immutableDllPath); cp.ReferencedAssemblies.Add("System.Runtime.dll"); } @@ -375,6 +378,15 @@ namespace Microsoft.Dafny } } 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) { -- cgit v1.2.3 From f057d2ec10bdf93bb8ef73cbb3ea80d56159faeb Mon Sep 17 00:00:00 2001 From: Bryan Parno Date: Wed, 1 Jul 2015 11:53:59 -0700 Subject: Add code to calculate various interesting statistics about Dafny files. --- Source/Dafny/DafnyOptions.cs | 14 +++- Source/Dafny/SccGraph.cs | 10 ++- Source/Dafny/Util.cs | 149 +++++++++++++++++++++++++++++++++++++- Source/DafnyDriver/DafnyDriver.cs | 7 ++ 4 files changed, 175 insertions(+), 5 deletions(-) (limited to 'Source/DafnyDriver/DafnyDriver.cs') diff --git a/Source/Dafny/DafnyOptions.cs b/Source/Dafny/DafnyOptions.cs index 125ab11e..af940439 100644 --- a/Source/Dafny/DafnyOptions.cs +++ b/Source/Dafny/DafnyOptions.cs @@ -56,6 +56,8 @@ namespace Microsoft.Dafny public bool AllowGlobals = false; public bool CountVerificationErrors = true; public bool Optimize = false; + public bool PrintStats = false; + public bool PrintFunctionCallGraph = false; protected override bool ParseOption(string name, Bpl.CommandLineOptionEngine.CommandLineParseState ps) { var args = ps.args; // convenient synonym @@ -172,6 +174,14 @@ namespace Microsoft.Dafny case "allowGlobals": AllowGlobals = true; return true; + + case "stats": + PrintStats = true; + return true; + + case "funcCallGraph": + PrintFunctionCallGraph = true; + return true; case "countVerificationErrors": { int countErrors = 1; // defaults to reporting verification errors @@ -267,7 +277,7 @@ namespace Microsoft.Dafny /noAutoReq Ignore autoReq attributes /allowGlobals Allow the implicit class '_default' to contain fields, instance functions, and instance methods. These class members are declared at the module scope, - outside of explicit classes. This command-line option is provided to simply + outside of explicit classes. This command-line option is provided to simplify a transition from the behavior in the language prior to version 1.9.3, from which point onward all functions and methods declared at the module scope are implicitly static and fields declarations are not allowed at the module scope. @@ -282,6 +292,8 @@ namespace Microsoft.Dafny System.Collections.Immutable.dll in the source directory to successfully compile). - passes /optimize flag to csc.exe. + /stats Print interesting statistics about the Dafny files supplied. + /funcCallGraph Print out the function call graph. Format is: func,mod=callee* "); base.Usage(); // also print the Boogie options } diff --git a/Source/Dafny/SccGraph.cs b/Source/Dafny/SccGraph.cs index 01a72fc5..20b4f65e 100644 --- a/Source/Dafny/SccGraph.cs +++ b/Source/Dafny/SccGraph.cs @@ -6,8 +6,8 @@ namespace Microsoft.Dafny { public class Graph where Node : class { - enum VisitedStatus { Unvisited, OnStack, Visited } - class Vertex { + public enum VisitedStatus { Unvisited, OnStack, Visited } + public class Vertex { public readonly Node N; public readonly List/*!*/ Successors = new List(); public List SccMembers; // non-null only for the representative of the SCC @@ -65,6 +65,10 @@ namespace Microsoft.Dafny { { } + public IEnumerable GetVertices() { + return vertices.Values; + } + /// /// Idempotently adds a vertex 'n' to the graph. /// @@ -97,7 +101,7 @@ namespace Microsoft.Dafny { /// /// Returns the vertex for 'n' if 'n' is in the graph. Otherwise, returns null. /// - Vertex FindVertex(Node n) { + public Vertex FindVertex(Node n) { Vertex v; if (vertices.TryGetValue(n, out v)) { Contract.Assert(v != null); // follows from postcondition of TryGetValue (since 'vertices' maps to the type Vertex!) diff --git a/Source/Dafny/Util.cs b/Source/Dafny/Util.cs index f9421659..63659696 100644 --- a/Source/Dafny/Util.cs +++ b/Source/Dafny/Util.cs @@ -8,7 +8,7 @@ using Microsoft.Boogie; namespace Microsoft.Dafny { - class Util + public class Util { public static string Comma(IEnumerable l, Func f) { return Comma(",", l, f); @@ -175,5 +175,152 @@ namespace Microsoft.Dafny { } } + /// + /// Class dedicated to traversing the function call graph + /// + class FunctionCallFinder : TopDownVisitor> { + protected override bool VisitOneExpr(Expression expr, ref List calls) { + if (expr is FunctionCallExpr) { + calls.Add(((FunctionCallExpr)expr).Function); + } + return true; + } + } + + static Graph BuildFunctionCallGraph(Dafny.Program program) { + Graph functionCallGraph = new Graph(); + FunctionCallFinder callFinder = new FunctionCallFinder(); + + foreach (var module in program.Modules) { + foreach (var decl in module.TopLevelDecls) { + if (decl is ClassDecl) { + var c = (ClassDecl)decl; + foreach (var member in c.Members) { + if (member is Function) { + var f = (Function)member; + + List calls = new List(); + foreach (var e in f.Reads) { if (e != null && e.E != null) { callFinder.Visit(e.E, calls); } } + foreach (var e in f.Req) { if (e != null) { callFinder.Visit(e, calls); } } + foreach (var e in f.Ens) { if (e != null) { callFinder.Visit(e, calls); } } + if (f.Body != null) { + callFinder.Visit(f.Body, calls); + } + + foreach (var callee in calls) { + functionCallGraph.AddEdge(f, callee); + } + } + } + } + } + } + + return functionCallGraph; + } + + /// + /// Prints the program's function call graph in a format suitable for consumption in other tools + /// + public static void PrintFunctionCallGraph(Dafny.Program program) { + var functionCallGraph = BuildFunctionCallGraph(program); + + foreach (var vertex in functionCallGraph.GetVertices()) { + var func = vertex.N; + Console.Write("{0},{1}=", func.CompileName, func.EnclosingClass.Module.CompileName); + foreach (var callee in vertex.Successors) { + Console.Write("{0} ", callee.N.CompileName); + } + Console.Write("\n"); + } + } + + /// + /// Generic statistic counter + /// + static void IncrementStat(IDictionary stats, string stat) { + ulong currentValue; + if (stats.TryGetValue(stat, out currentValue)) { + stats[stat] += 1; + } else { + stats.Add(stat, 1); + } + } + + /// + /// Track the maximum value of some statistic + /// + static void UpdateMax(IDictionary stats, string stat, ulong val) { + ulong currentValue; + if (stats.TryGetValue(stat, out currentValue)) { + if (val > currentValue) { + stats[stat] = val; + } + } else { + stats.Add(stat, val); + } + } + + /// + /// Compute various interesting statistics about the Dafny program + /// + public static void PrintStats(Dafny.Program program) { + SortedDictionary stats = new SortedDictionary(); + + foreach (var module in program.Modules) { + IncrementStat(stats, "Modules"); + UpdateMax(stats, "Module height (max)", (ulong)module.Height); + + ulong num_scc = (ulong)module.CallGraph.TopologicallySortedComponents().Count; + UpdateMax(stats, "Call graph width (max)", num_scc); + + foreach (var decl in module.TopLevelDecls) { + if (decl is DatatypeDecl) { + IncrementStat(stats, "Datatypes"); + } else if (decl is ClassDecl) { + var c = (ClassDecl)decl; + if (c.Name != "_default") { + IncrementStat(stats, "Classes"); + } + + foreach (var member in c.Members) { + if (member is Function) { + IncrementStat(stats, "Functions (total)"); + var f = (Function)member; + if (f.IsRecursive) { + IncrementStat(stats, "Functions recursive"); + } + } else if (member is Method) { + IncrementStat(stats, "Methods (total)"); + var method = (Method)member; + if (method.IsRecursive) { + IncrementStat(stats, "Methods recursive"); + } + if (method.IsGhost) { + IncrementStat(stats, "Methods ghost"); + } + } + } + } + } + } + + // Print out the results, with some nice formatting + Console.WriteLine(""); + Console.WriteLine("Statistics"); + Console.WriteLine("----------"); + + int max_key_length = 0; + foreach (var key in stats.Keys) { + if (key.Length > max_key_length) { + max_key_length = key.Length; + } + } + + foreach (var keypair in stats) { + string keyString = keypair.Key.PadRight(max_key_length + 2); + Console.WriteLine("{0} {1,4}", keyString, keypair.Value); + } + } } } diff --git a/Source/DafnyDriver/DafnyDriver.cs b/Source/DafnyDriver/DafnyDriver.cs index ce4d726f..9fdc9320 100644 --- a/Source/DafnyDriver/DafnyDriver.cs +++ b/Source/DafnyDriver/DafnyDriver.cs @@ -199,6 +199,13 @@ namespace Microsoft.Dafny } exitValue = allOk ? ExitValue.VERIFIED : ExitValue.NOT_VERIFIED; } + + if (err == null && dafnyProgram != null && DafnyOptions.O.PrintStats) { + Util.PrintStats(dafnyProgram); + } + if (err == null && dafnyProgram != null && DafnyOptions.O.PrintFunctionCallGraph) { + Util.PrintFunctionCallGraph(dafnyProgram); + } } return exitValue; } -- cgit v1.2.3 From 3f886d1789d50400ffba2befdc2ae0e8d5c79cbe Mon Sep 17 00:00:00 2001 From: Clément Pit--Claudel Date: Thu, 23 Jul 2015 11:57:19 -0700 Subject: Fix: Unify column numbers in Dafny's errors Dafny counts from 0, but Boogie counts from 1. Tokens are 1-based. Thus when we print tokens, we need to decrement the column number. This was done for resolver errors, but not for verification or parsing errors. In addition, parsing errors were inconsistent with resolution errors case-wise. Unfortunately, the fix affects the output of many tests. --- Source/Dafny/Parser.cs | 12 ++- Source/DafnyDriver/DafnyDriver.cs | 8 +- Test/dafny0/AdvancedLHS.dfy.expect | 2 +- Test/dafny0/Array.dfy.expect | 46 +++++----- Test/dafny0/AutoReq.dfy.expect | 38 ++++----- Test/dafny0/Backticks.dfy.expect | 4 +- Test/dafny0/BadFunction.dfy.expect | 2 +- Test/dafny0/Basics.dfy.expect | 36 ++++---- Test/dafny0/Calculations.dfy.expect | 12 +-- Test/dafny0/Char.dfy.expect | 6 +- Test/dafny0/CoPrefix.dfy.expect | 30 +++---- Test/dafny0/CoinductiveProofs.dfy.expect | 42 +++++----- Test/dafny0/Comprehensions.dfy.expect | 2 +- Test/dafny0/ComputationsLoop.dfy.expect | 4 +- Test/dafny0/ComputationsLoop2.dfy.expect | 6 +- Test/dafny0/ComputationsNeg.dfy.expect | 14 ++-- Test/dafny0/ControlStructures.dfy.expect | 20 ++--- Test/dafny0/Corecursion.dfy.expect | 16 ++-- Test/dafny0/DTypes.dfy.expect | 24 +++--- Test/dafny0/Datatypes.dfy.expect | 26 +++--- Test/dafny0/Definedness.dfy.expect | 98 +++++++++++----------- Test/dafny0/DeterministicPick.dfy.expect | 2 +- Test/dafny0/DiamondImports.dfy.expect | 10 +-- Test/dafny0/Fuel.dfy.expect | 50 +++++------ Test/dafny0/FunctionSpecifications.dfy.expect | 38 ++++----- Test/dafny0/IMaps.dfy.expect | 2 +- Test/dafny0/Include.dfy.expect | 10 +-- Test/dafny0/Includee.dfy.expect | 10 +-- Test/dafny0/IndexIntoUpdate.dfy.expect | 2 +- Test/dafny0/InductivePredicates.dfy.expect | 4 +- Test/dafny0/Inverses.dfy.expect | 8 +- Test/dafny0/Iterators.dfy.expect | 44 +++++----- Test/dafny0/LetExpr.dfy.expect | 18 ++-- Test/dafny0/LhsDuplicates.dfy.expect | 12 +-- Test/dafny0/LoopModifies.dfy.expect | 18 ++-- Test/dafny0/Maps.dfy.expect | 4 +- Test/dafny0/ModifyStmt.dfy.expect | 22 ++--- Test/dafny0/Modules0.dfy.expect | 4 +- Test/dafny0/Modules1.dfy.expect | 12 +-- Test/dafny0/MultiDimArray.dfy.expect | 4 +- Test/dafny0/MultiSets.dfy.expect | 14 ++-- Test/dafny0/NatTypes.dfy.expect | 18 ++-- Test/dafny0/Newtypes.dfy.expect | 26 +++--- Test/dafny0/OpaqueFunctions.dfy.expect | 52 ++++++------ Test/dafny0/Parallel.dfy.expect | 20 ++--- Test/dafny0/ParseErrors.dfy.expect | 32 +++---- Test/dafny0/PredExpr.dfy.expect | 8 +- Test/dafny0/Predicates.dfy.expect | 26 +++--- Test/dafny0/Protected.dfy.expect | 10 +-- Test/dafny0/RankNeg.dfy.expect | 8 +- Test/dafny0/Reads.dfy.expect | 18 ++-- Test/dafny0/RealCompare.dfy.expect | 10 +-- Test/dafny0/RealTypes.dfy.expect | 10 +-- Test/dafny0/Refinement.dfy.expect | 36 ++++---- Test/dafny0/Skeletons.dfy.expect | 4 +- Test/dafny0/SmallTests.dfy.expect | 76 ++++++++--------- Test/dafny0/SplitExpr.dfy.expect | 4 +- Test/dafny0/StatementExpressions.dfy.expect | 10 +-- Test/dafny0/Superposition.dfy.expect | 12 +-- Test/dafny0/Termination.dfy.expect | 16 ++-- .../Trait/TraitUsingParentMembers.dfy.expect | 2 +- Test/dafny0/Trait/TraitsDecreases.dfy.expect | 22 ++--- Test/dafny0/Tuples.dfy.expect | 4 +- Test/dafny0/TypeAntecedents.dfy.expect | 8 +- Test/dafny0/TypeParameters.dfy.expect | 30 +++---- Test/dafny0/columns.dfy | 10 +++ Test/dafny0/columns.dfy.expect | 18 ++++ Test/dafny0/snapshots/Snapshots0.run.dfy.expect | 2 +- Test/dafny0/snapshots/Snapshots1.run.dfy.expect | 2 +- Test/dafny0/snapshots/Snapshots2.run.dfy.expect | 2 +- Test/dafny0/snapshots/Snapshots3.run.dfy.expect | 4 +- Test/dafny0/snapshots/Snapshots4.run.dfy.expect | 4 +- Test/dafny0/snapshots/Snapshots6.run.dfy.expect | 2 +- Test/dafny0/snapshots/Snapshots7.run.dfy.expect | 2 +- Test/dafny1/MoreInduction.dfy.expect | 16 ++-- Test/dafny2/SnapshotableTrees.dfy.expect | 4 +- Test/dafny4/BinarySearch.dfy.expect | 2 +- Test/dafny4/Bug73.dfy.expect | 4 +- Test/dafny4/SoftwareFoundations-Basics.dfy.expect | 2 +- Test/hofs/Apply.dfy.expect | 2 +- Test/hofs/Classes.dfy.expect | 4 +- Test/hofs/Field.dfy.expect | 8 +- Test/hofs/FnRef.dfy.expect | 8 +- Test/hofs/Frame.dfy.expect | 14 ++-- Test/hofs/Lambda.dfy.expect | 2 +- Test/hofs/LambdaParsefail.dfy.expect | 10 +-- Test/hofs/LambdaParsefail2.dfy.expect | 2 +- Test/hofs/Naked.dfy.expect | 24 +++--- Test/hofs/OneShot.dfy.expect | 6 +- Test/hofs/ReadsReads.dfy.expect | 16 ++-- Test/hofs/Simple.dfy.expect | 12 +-- Test/hofs/Twice.dfy.expect | 4 +- Test/irondafny0/inheritreqs0.dfy.expect | 4 +- Test/irondafny0/inheritreqs1.dfy.expect | 4 +- Test/irondafny0/xrefine1.dfy.expect | 4 +- 95 files changed, 714 insertions(+), 682 deletions(-) create mode 100644 Test/dafny0/columns.dfy create mode 100644 Test/dafny0/columns.dfy.expect (limited to 'Source/DafnyDriver/DafnyDriver.cs') diff --git a/Source/Dafny/Parser.cs b/Source/Dafny/Parser.cs index 01438f68..d50a4dd6 100644 --- a/Source/Dafny/Parser.cs +++ b/Source/Dafny/Parser.cs @@ -4429,8 +4429,8 @@ List/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo public class Errors { public int count = 0; // number of errors detected public System.IO.TextWriter/*!*/ errorStream = Console.Out; // error messages go to this stream - public string errMsgFormat = "{0}({1},{2}): error: {3}"; // 0=filename, 1=line, 2=column, 3=text - public string warningMsgFormat = "{0}({1},{2}): warning: {3}"; // 0=filename, 1=line, 2=column, 3=text + public string errMsgFormat = "{0}({1},{2}): Error: {3}"; // 0=filename, 1=line, 2=column, 3=text + public string warningMsgFormat = "{0}({1},{2}): Warning: {3}"; // 0=filename, 1=line, 2=column, 3=text public void SynErr(string filename, int line, int col, int n) { SynErr(filename, line, col, GetSyntaxErrorString(n)); @@ -4438,7 +4438,7 @@ public class Errors { public virtual void SynErr(string filename, int line, int col, string/*!*/ msg) { Contract.Requires(msg != null); - errorStream.WriteLine(errMsgFormat, filename, line, col, msg); + errorStream.WriteLine(errMsgFormat, filename, line, col - 1, msg); count++; } @@ -4701,7 +4701,7 @@ public class Errors { public virtual void SemErr(string filename, int line, int col, string/*!*/ msg) { Contract.Requires(msg != null); - errorStream.WriteLine(errMsgFormat, filename, line, col, msg); + errorStream.WriteLine(errMsgFormat, filename, line, col - 1, msg); count++; } @@ -4713,7 +4713,7 @@ public class Errors { public virtual void Warning(string filename, int line, int col, string msg) { Contract.Requires(msg != null); - errorStream.WriteLine(warningMsgFormat, filename, line, col, msg); + errorStream.WriteLine(warningMsgFormat, filename, line, col - 1, msg); } } // Errors @@ -4721,6 +4721,4 @@ public class Errors { public class FatalError: Exception { public FatalError(string m): base(m) {} } - - } \ No newline at end of file diff --git a/Source/DafnyDriver/DafnyDriver.cs b/Source/DafnyDriver/DafnyDriver.cs index 9fdc9320..d22899ab 100644 --- a/Source/DafnyDriver/DafnyDriver.cs +++ b/Source/DafnyDriver/DafnyDriver.cs @@ -273,7 +273,13 @@ namespace Microsoft.Dafny { public override void ReportBplError(IToken tok, string message, bool error, TextWriter tw, string category = null) { - base.ReportBplError(tok, message, error, tw, category); + // Dafny has 0-indexed columns, but Boogie counts from 1 + var realigned_tok = new Token(tok.line, tok.col - 1); + realigned_tok.kind = tok.kind; + realigned_tok.pos = tok.pos; + realigned_tok.val = tok.val; + realigned_tok.filename = tok.filename; + base.ReportBplError(realigned_tok, message, error, tw, category); if (tok is Dafny.NestedToken) { diff --git a/Test/dafny0/AdvancedLHS.dfy.expect b/Test/dafny0/AdvancedLHS.dfy.expect index cb817605..aab12cfc 100644 --- a/Test/dafny0/AdvancedLHS.dfy.expect +++ b/Test/dafny0/AdvancedLHS.dfy.expect @@ -1,4 +1,4 @@ -AdvancedLHS.dfy(34,23): Error: target object may be null +AdvancedLHS.dfy(34,22): Error: target object may be null Execution trace: (0,0): anon0 (0,0): anon15_Else diff --git a/Test/dafny0/Array.dfy.expect b/Test/dafny0/Array.dfy.expect index 59dcb4bf..40fb318d 100644 --- a/Test/dafny0/Array.dfy.expect +++ b/Test/dafny0/Array.dfy.expect @@ -1,16 +1,16 @@ -Array.dfy(13,8): Error: assignment may update an array element not in the enclosing context's modifies clause +Array.dfy(13,7): Error: assignment may update an array element not in the enclosing context's modifies clause Execution trace: (0,0): anon0 (0,0): anon5_Then (0,0): anon2 (0,0): anon6_Then -Array.dfy(20,16): Error: target object may be null +Array.dfy(20,15): Error: target object may be null Execution trace: (0,0): anon0 -Array.dfy(27,6): Error: index out of range +Array.dfy(27,5): Error: index out of range Execution trace: (0,0): anon0 -Array.dfy(51,20): Error: assertion violation +Array.dfy(51,19): Error: assertion violation Execution trace: (0,0): anon0 (0,0): anon12_Then @@ -21,19 +21,19 @@ Execution trace: (0,0): anon16_Then (0,0): anon9 (0,0): anon11 -Array.dfy(59,8): Error: assignment may update an array element not in the enclosing context's modifies clause +Array.dfy(59,7): Error: assignment may update an array element not in the enclosing context's modifies clause Execution trace: (0,0): anon0 (0,0): anon5_Then (0,0): anon2 (0,0): anon6_Then -Array.dfy(66,8): Error: assignment may update an array element not in the enclosing context's modifies clause +Array.dfy(66,7): Error: assignment may update an array element not in the enclosing context's modifies clause Execution trace: (0,0): anon0 (0,0): anon5_Then (0,0): anon2 (0,0): anon6_Then -Array.dfy(110,21): Error: upper bound below lower bound or above length of array +Array.dfy(110,20): Error: upper bound below lower bound or above length of array Execution trace: (0,0): anon0 (0,0): anon14_Else @@ -41,7 +41,7 @@ Execution trace: (0,0): anon19_Then (0,0): anon20_Then (0,0): anon11 -Array.dfy(120,8): Error: insufficient reads clause to read the indicated range of array elements +Array.dfy(120,7): Error: insufficient reads clause to read the indicated range of array elements Execution trace: (0,0): anon0 (0,0): anon10_Else @@ -49,7 +49,7 @@ Execution trace: (0,0): anon12_Then (0,0): anon13_Then (0,0): anon9 -Array.dfy(122,8): Error: insufficient reads clause to read the indicated range of array elements +Array.dfy(122,7): Error: insufficient reads clause to read the indicated range of array elements Execution trace: (0,0): anon0 (0,0): anon10_Else @@ -57,7 +57,7 @@ Execution trace: (0,0): anon12_Then (0,0): anon13_Else (0,0): anon9 -Array.dfy(123,8): Error: insufficient reads clause to read the indicated range of array elements +Array.dfy(123,7): Error: insufficient reads clause to read the indicated range of array elements Execution trace: (0,0): anon0 (0,0): anon10_Else @@ -65,7 +65,7 @@ Execution trace: (0,0): anon12_Then (0,0): anon13_Else (0,0): anon9 -Array.dfy(124,8): Error: insufficient reads clause to read the indicated range of array elements +Array.dfy(124,7): Error: insufficient reads clause to read the indicated range of array elements Execution trace: (0,0): anon0 (0,0): anon10_Else @@ -73,45 +73,45 @@ Execution trace: (0,0): anon12_Then (0,0): anon13_Else (0,0): anon9 -Array.dfy(163,6): Error: insufficient reads clause to read array element +Array.dfy(163,5): Error: insufficient reads clause to read array element Execution trace: (0,0): anon0 (0,0): anon8_Else (0,0): anon9_Then (0,0): anon10_Then (0,0): anon7 -Array.dfy(171,6): Error: insufficient reads clause to read array element +Array.dfy(171,5): Error: insufficient reads clause to read array element Execution trace: (0,0): anon0 (0,0): anon8_Else (0,0): anon9_Then (0,0): anon10_Then (0,0): anon7 -Array.dfy(187,6): Error: assignment may update an array element not in the enclosing context's modifies clause +Array.dfy(187,5): Error: assignment may update an array element not in the enclosing context's modifies clause Execution trace: (0,0): anon0 -Array.dfy(194,6): Error: assignment may update an array element not in the enclosing context's modifies clause +Array.dfy(194,5): Error: assignment may update an array element not in the enclosing context's modifies clause Execution trace: (0,0): anon0 -Array.dfy(219,1): Error BP5003: A postcondition might not hold on this return path. -Array.dfy(218,11): Related location: This is the postcondition that might not hold. +Array.dfy(219,0): Error BP5003: A postcondition might not hold on this return path. +Array.dfy(218,10): Related location: This is the postcondition that might not hold. Execution trace: (0,0): anon0 -Array.dfy(243,1): Error BP5003: A postcondition might not hold on this return path. -Array.dfy(242,11): Related location: This is the postcondition that might not hold. +Array.dfy(243,0): Error BP5003: A postcondition might not hold on this return path. +Array.dfy(242,10): Related location: This is the postcondition that might not hold. Execution trace: (0,0): anon0 -Array.dfy(249,1): Error BP5003: A postcondition might not hold on this return path. -Array.dfy(248,11): Related location: This is the postcondition that might not hold. +Array.dfy(249,0): Error BP5003: A postcondition might not hold on this return path. +Array.dfy(248,10): Related location: This is the postcondition that might not hold. Execution trace: (0,0): anon0 -Array.dfy(264,10): Error: value assigned to a nat must be non-negative +Array.dfy(264,9): Error: value assigned to a nat must be non-negative Execution trace: (0,0): anon0 (0,0): anon5_Then (0,0): anon2 (0,0): anon6_Then -Array.dfy(265,5): Error: value assigned to a nat must be non-negative +Array.dfy(265,4): Error: value assigned to a nat must be non-negative Execution trace: (0,0): anon0 (0,0): anon5_Then diff --git a/Test/dafny0/AutoReq.dfy.expect b/Test/dafny0/AutoReq.dfy.expect index 8486716d..b4b34e14 100644 --- a/Test/dafny0/AutoReq.dfy.expect +++ b/Test/dafny0/AutoReq.dfy.expect @@ -1,43 +1,43 @@ -AutoReq.dfy(247,5): Error: possible violation of function precondition -AutoReq.dfy(239,14): Related location +AutoReq.dfy(247,4): Error: possible violation of function precondition +AutoReq.dfy(239,13): Related location Execution trace: (0,0): anon0 (0,0): anon4_Else -AutoReq.dfy(13,3): Error: possible violation of function precondition -AutoReq.dfy(5,14): Related location +AutoReq.dfy(13,2): Error: possible violation of function precondition +AutoReq.dfy(5,13): Related location Execution trace: (0,0): anon0 (0,0): anon4_Else -AutoReq.dfy(25,3): Error: possible violation of function precondition -AutoReq.dfy(5,14): Related location +AutoReq.dfy(25,2): Error: possible violation of function precondition +AutoReq.dfy(5,13): Related location Execution trace: (0,0): anon0 (0,0): anon4_Else -AutoReq.dfy(38,12): Error: assertion violation -AutoReq.dfy(31,13): Related location -AutoReq.dfy(7,5): Related location +AutoReq.dfy(38,11): Error: assertion violation +AutoReq.dfy(31,12): Related location +AutoReq.dfy(7,4): Related location Execution trace: (0,0): anon0 (0,0): anon9_Then -AutoReq.dfy(38,12): Error: possible violation of function precondition -AutoReq.dfy(5,14): Related location +AutoReq.dfy(38,11): Error: possible violation of function precondition +AutoReq.dfy(5,13): Related location Execution trace: (0,0): anon0 (0,0): anon9_Then -AutoReq.dfy(40,12): Error: assertion violation -AutoReq.dfy(31,27): Related location -AutoReq.dfy(7,5): Related location +AutoReq.dfy(40,11): Error: assertion violation +AutoReq.dfy(31,26): Related location +AutoReq.dfy(7,4): Related location Execution trace: (0,0): anon0 (0,0): anon10_Then -AutoReq.dfy(40,12): Error: possible violation of function precondition -AutoReq.dfy(5,14): Related location +AutoReq.dfy(40,11): Error: possible violation of function precondition +AutoReq.dfy(5,13): Related location Execution trace: (0,0): anon0 (0,0): anon10_Then -AutoReq.dfy(45,12): Error: assertion violation -AutoReq.dfy(31,13): Related location -AutoReq.dfy(7,5): Related location +AutoReq.dfy(45,11): Error: assertion violation +AutoReq.dfy(31,12): Related location +AutoReq.dfy(7,4): Related location Execution trace: (0,0): anon0 (0,0): anon11_Then diff --git a/Test/dafny0/Backticks.dfy.expect b/Test/dafny0/Backticks.dfy.expect index 57761ab4..58977413 100644 --- a/Test/dafny0/Backticks.dfy.expect +++ b/Test/dafny0/Backticks.dfy.expect @@ -1,10 +1,10 @@ -Backticks.dfy(38,5): Error: insufficient reads clause to invoke function +Backticks.dfy(38,4): Error: insufficient reads clause to invoke function Execution trace: (0,0): anon0 (0,0): anon7_Else (0,0): anon8_Else (0,0): anon6 -Backticks.dfy(77,8): Error: call may violate context's modifies clause +Backticks.dfy(77,7): Error: call may violate context's modifies clause Execution trace: (0,0): anon0 (0,0): anon3_Then diff --git a/Test/dafny0/BadFunction.dfy.expect b/Test/dafny0/BadFunction.dfy.expect index 9c4ae81d..1af2608d 100644 --- a/Test/dafny0/BadFunction.dfy.expect +++ b/Test/dafny0/BadFunction.dfy.expect @@ -1,4 +1,4 @@ -BadFunction.dfy(9,3): Error: failure to decrease termination measure +BadFunction.dfy(9,2): Error: failure to decrease termination measure Execution trace: (0,0): anon0 (0,0): anon4_Else diff --git a/Test/dafny0/Basics.dfy.expect b/Test/dafny0/Basics.dfy.expect index f28df20a..65d5d101 100644 --- a/Test/dafny0/Basics.dfy.expect +++ b/Test/dafny0/Basics.dfy.expect @@ -1,8 +1,8 @@ -Basics.dfy(45,14): Error: assertion violation +Basics.dfy(45,13): Error: assertion violation Execution trace: (0,0): anon0 (0,0): anon3_Else -Basics.dfy(69,42): Error: assertion violation +Basics.dfy(69,41): Error: assertion violation Execution trace: (0,0): anon0 (0,0): anon13_Then @@ -12,7 +12,7 @@ Execution trace: Basics.dfy(69,82): anon17_Else Basics.dfy(69,95): anon18_Else (0,0): anon12 -Basics.dfy(93,14): Error: assertion violation +Basics.dfy(93,13): Error: assertion violation Execution trace: (0,0): anon0 Basics.dfy(83,14): anon27_Else @@ -27,7 +27,7 @@ Execution trace: Basics.dfy(91,13): anon34_Else (0,0): anon35_Then (0,0): anon15 -Basics.dfy(99,14): Error: assertion violation +Basics.dfy(99,13): Error: assertion violation Execution trace: (0,0): anon0 Basics.dfy(83,14): anon27_Else @@ -42,7 +42,7 @@ Execution trace: Basics.dfy(97,19): anon40_Else (0,0): anon41_Then (0,0): anon26 -Basics.dfy(112,28): Error: target object may be null +Basics.dfy(112,27): Error: target object may be null Execution trace: (0,0): anon0 Basics.dfy(105,20): anon13_Else @@ -52,7 +52,7 @@ Execution trace: Basics.dfy(107,24): anon15_Else (0,0): anon6 (0,0): anon16_Then -Basics.dfy(114,14): Error: target object may be null +Basics.dfy(114,13): Error: target object may be null Execution trace: (0,0): anon0 Basics.dfy(105,20): anon13_Else @@ -62,11 +62,11 @@ Execution trace: Basics.dfy(107,24): anon15_Else (0,0): anon6 (0,0): anon16_Else -Basics.dfy(149,16): Error: assertion violation +Basics.dfy(149,15): Error: assertion violation Execution trace: (0,0): anon0 (0,0): anon10_Then -Basics.dfy(168,10): Error: when left-hand sides 0 and 1 may refer to the same location, they must be assigned the same value +Basics.dfy(168,9): Error: when left-hand sides 0 and 1 may refer to the same location, they must be assigned the same value Execution trace: (0,0): anon0 (0,0): anon10_Then @@ -75,28 +75,28 @@ Execution trace: (0,0): anon6 (0,0): anon12_Then (0,0): anon9 -Basics.dfy(182,10): Error: when left-hand sides 0 and 1 refer to the same location, they must be assigned the same value +Basics.dfy(182,9): Error: when left-hand sides 0 and 1 refer to the same location, they must be assigned the same value Execution trace: (0,0): anon0 -Basics.dfy(194,19): Error: assertion violation +Basics.dfy(194,18): Error: assertion violation Execution trace: (0,0): anon0 (0,0): anon11_Then -Basics.dfy(196,10): Error: assignment may update an object not in the enclosing context's modifies clause +Basics.dfy(196,9): Error: assignment may update an object not in the enclosing context's modifies clause Execution trace: (0,0): anon0 (0,0): anon3 -Basics.dfy(196,10): Error: target object may be null +Basics.dfy(196,9): Error: target object may be null Execution trace: (0,0): anon0 (0,0): anon3 -Basics.dfy(201,12): Error: left-hand sides 0 and 1 may refer to the same location +Basics.dfy(201,11): Error: left-hand sides 0 and 1 may refer to the same location Execution trace: (0,0): anon0 (0,0): anon11_Then (0,0): anon3 (0,0): anon12_Then -Basics.dfy(212,15): Error: assertion violation +Basics.dfy(212,14): Error: assertion violation Execution trace: (0,0): anon0 (0,0): anon11_Then @@ -106,19 +106,19 @@ Execution trace: (0,0): anon13_Then (0,0): anon8 (0,0): anon14_Then -Basics.dfy(274,10): Error: when left-hand sides 0 and 1 refer to the same location, they must be assigned the same value +Basics.dfy(274,9): Error: when left-hand sides 0 and 1 refer to the same location, they must be assigned the same value Execution trace: (0,0): anon0 -Basics.dfy(465,12): Error: assertion violation +Basics.dfy(465,11): Error: assertion violation Execution trace: (0,0): anon0 (0,0): anon4_Then (0,0): anon3 -Basics.dfy(476,19): Error: assertion violation +Basics.dfy(476,18): Error: assertion violation Execution trace: (0,0): anon0 (0,0): anon4_Else -Basics.dfy(478,12): Error: assertion violation +Basics.dfy(478,11): Error: assertion violation Execution trace: (0,0): anon0 (0,0): anon4_Then diff --git a/Test/dafny0/Calculations.dfy.expect b/Test/dafny0/Calculations.dfy.expect index 3427a5cb..d4559f53 100644 --- a/Test/dafny0/Calculations.dfy.expect +++ b/Test/dafny0/Calculations.dfy.expect @@ -1,24 +1,24 @@ -Calculations.dfy(7,6): Error: index out of range +Calculations.dfy(7,5): Error: index out of range Execution trace: (0,0): anon0 (0,0): anon24_Then -Calculations.dfy(12,15): Error: index out of range +Calculations.dfy(12,14): Error: index out of range Execution trace: (0,0): anon0 (0,0): anon26_Then -Calculations.dfy(12,19): Error: assertion violation +Calculations.dfy(12,18): Error: assertion violation Execution trace: (0,0): anon0 (0,0): anon26_Then -Calculations.dfy(56,12): Error: assertion violation +Calculations.dfy(56,11): Error: assertion violation Execution trace: (0,0): anon0 Calculations.dfy(51,3): anon5_Else -Calculations.dfy(79,15): Error: index out of range +Calculations.dfy(79,14): Error: index out of range Execution trace: (0,0): anon0 (0,0): anon12_Then -Calculations.dfy(79,19): Error: assertion violation +Calculations.dfy(79,18): Error: assertion violation Execution trace: (0,0): anon0 (0,0): anon12_Then diff --git a/Test/dafny0/Char.dfy.expect b/Test/dafny0/Char.dfy.expect index 55418934..874aaa65 100644 --- a/Test/dafny0/Char.dfy.expect +++ b/Test/dafny0/Char.dfy.expect @@ -1,14 +1,14 @@ -Char.dfy(48,21): Error: assertion violation +Char.dfy(48,20): Error: assertion violation Execution trace: (0,0): anon0 (0,0): anon9_Then (0,0): anon10_Then -Char.dfy(52,21): Error: assertion violation +Char.dfy(52,20): Error: assertion violation Execution trace: (0,0): anon0 (0,0): anon9_Then (0,0): anon11_Else -Char.dfy(63,17): Error: assertion violation +Char.dfy(63,16): Error: assertion violation Execution trace: (0,0): anon0 (0,0): anon5_Else diff --git a/Test/dafny0/CoPrefix.dfy.expect b/Test/dafny0/CoPrefix.dfy.expect index c92a09c1..a7295367 100644 --- a/Test/dafny0/CoPrefix.dfy.expect +++ b/Test/dafny0/CoPrefix.dfy.expect @@ -1,48 +1,48 @@ -CoPrefix.dfy(164,3): Error BP5003: A postcondition might not hold on this return path. -CoPrefix.dfy(163,15): Related location: This is the postcondition that might not hold. +CoPrefix.dfy(164,2): Error BP5003: A postcondition might not hold on this return path. +CoPrefix.dfy(163,14): Related location: This is the postcondition that might not hold. Execution trace: (0,0): anon0 (0,0): anon3_Else -CoPrefix.dfy(169,3): Error BP5003: A postcondition might not hold on this return path. -CoPrefix.dfy(168,15): Related location: This is the postcondition that might not hold. +CoPrefix.dfy(169,2): Error BP5003: A postcondition might not hold on this return path. +CoPrefix.dfy(168,14): Related location: This is the postcondition that might not hold. Execution trace: (0,0): anon0 (0,0): anon3_Else -CoPrefix.dfy(176,11): Error: cannot prove termination; try supplying a decreases clause +CoPrefix.dfy(176,10): Error: cannot prove termination; try supplying a decreases clause Execution trace: (0,0): anon0 (0,0): anon3_Then -CoPrefix.dfy(63,57): Error: failure to decrease termination measure +CoPrefix.dfy(63,56): Error: failure to decrease termination measure Execution trace: (0,0): anon0 (0,0): anon7_Then (0,0): anon8_Else (0,0): anon9_Then -CoPrefix.dfy(76,56): Error: cannot prove termination; try supplying a decreases clause +CoPrefix.dfy(76,55): Error: cannot prove termination; try supplying a decreases clause Execution trace: (0,0): anon0 (0,0): anon7_Then (0,0): anon8_Else (0,0): anon9_Then -CoPrefix.dfy(114,1): Error BP5003: A postcondition might not hold on this return path. -CoPrefix.dfy(113,11): Related location: This is the postcondition that might not hold. -CoPrefix.dfy(101,17): Related location +CoPrefix.dfy(114,0): Error BP5003: A postcondition might not hold on this return path. +CoPrefix.dfy(113,10): Related location: This is the postcondition that might not hold. +CoPrefix.dfy(101,16): Related location Execution trace: (0,0): anon0 (0,0): anon3_Then -CoPrefix.dfy(138,25): Error: assertion violation +CoPrefix.dfy(138,24): Error: assertion violation Execution trace: (0,0): anon0 (0,0): anon9_Then (0,0): anon10_Then -CoPrefix.dfy(142,25): Error: assertion violation -CoPrefix.dfy(117,23): Related location +CoPrefix.dfy(142,24): Error: assertion violation +CoPrefix.dfy(117,22): Related location Execution trace: (0,0): anon0 (0,0): anon9_Then (0,0): anon12_Then -CoPrefix.dfy(151,1): Error BP5003: A postcondition might not hold on this return path. -CoPrefix.dfy(150,11): Related location: This is the postcondition that might not hold. +CoPrefix.dfy(151,0): Error BP5003: A postcondition might not hold on this return path. +CoPrefix.dfy(150,10): Related location: This is the postcondition that might not hold. Execution trace: (0,0): anon0 (0,0): anon3_Else diff --git a/Test/dafny0/CoinductiveProofs.dfy.expect b/Test/dafny0/CoinductiveProofs.dfy.expect index 12ce2f01..2a5a2b0b 100644 --- a/Test/dafny0/CoinductiveProofs.dfy.expect +++ b/Test/dafny0/CoinductiveProofs.dfy.expect @@ -1,48 +1,48 @@ -CoinductiveProofs.dfy(29,12): Error: assertion violation -CoinductiveProofs.dfy(13,17): Related location +CoinductiveProofs.dfy(29,11): Error: assertion violation +CoinductiveProofs.dfy(13,16): Related location Execution trace: (0,0): anon0 (0,0): anon5_Then (0,0): anon6_Then -CoinductiveProofs.dfy(59,1): Error BP5003: A postcondition might not hold on this return path. -CoinductiveProofs.dfy(58,11): Related location: This is the postcondition that might not hold. -CoinductiveProofs.dfy(54,3): Related location +CoinductiveProofs.dfy(59,0): Error BP5003: A postcondition might not hold on this return path. +CoinductiveProofs.dfy(58,10): Related location: This is the postcondition that might not hold. +CoinductiveProofs.dfy(54,2): Related location Execution trace: (0,0): anon0 (0,0): anon3_Then -CoinductiveProofs.dfy(74,12): Error: assertion violation -CoinductiveProofs.dfy(54,3): Related location +CoinductiveProofs.dfy(74,11): Error: assertion violation +CoinductiveProofs.dfy(54,2): Related location Execution trace: (0,0): anon0 (0,0): anon5_Then (0,0): anon6_Then -CoinductiveProofs.dfy(91,1): Error BP5003: A postcondition might not hold on this return path. -CoinductiveProofs.dfy(90,11): Related location: This is the postcondition that might not hold. -CoinductiveProofs.dfy(80,3): Related location +CoinductiveProofs.dfy(91,0): Error BP5003: A postcondition might not hold on this return path. +CoinductiveProofs.dfy(90,10): Related location: This is the postcondition that might not hold. +CoinductiveProofs.dfy(80,2): Related location Execution trace: (0,0): anon0 (0,0): anon3_Then -CoinductiveProofs.dfy(100,12): Error: assertion violation -CoinductiveProofs.dfy(80,3): Related location +CoinductiveProofs.dfy(100,11): Error: assertion violation +CoinductiveProofs.dfy(80,2): Related location Execution trace: (0,0): anon0 (0,0): anon5_Then (0,0): anon6_Then -CoinductiveProofs.dfy(111,1): Error BP5003: A postcondition might not hold on this return path. -CoinductiveProofs.dfy(110,11): Related location: This is the postcondition that might not hold. -CoinductiveProofs.dfy(106,3): Related location +CoinductiveProofs.dfy(111,0): Error BP5003: A postcondition might not hold on this return path. +CoinductiveProofs.dfy(110,10): Related location: This is the postcondition that might not hold. +CoinductiveProofs.dfy(106,2): Related location Execution trace: (0,0): anon0 (0,0): anon3_Then -CoinductiveProofs.dfy(150,1): Error BP5003: A postcondition might not hold on this return path. -CoinductiveProofs.dfy(149,22): Related location: This is the postcondition that might not hold. -CoinductiveProofs.dfy(4,24): Related location +CoinductiveProofs.dfy(150,0): Error BP5003: A postcondition might not hold on this return path. +CoinductiveProofs.dfy(149,21): Related location: This is the postcondition that might not hold. +CoinductiveProofs.dfy(4,23): Related location Execution trace: (0,0): anon0 (0,0): anon3_Then -CoinductiveProofs.dfy(156,1): Error BP5003: A postcondition might not hold on this return path. -CoinductiveProofs.dfy(155,22): Related location: This is the postcondition that might not hold. -CoinductiveProofs.dfy(4,24): Related location +CoinductiveProofs.dfy(156,0): Error BP5003: A postcondition might not hold on this return path. +CoinductiveProofs.dfy(155,21): Related location: This is the postcondition that might not hold. +CoinductiveProofs.dfy(4,23): Related location Execution trace: (0,0): anon0 (0,0): anon3_Then diff --git a/Test/dafny0/Comprehensions.dfy.expect b/Test/dafny0/Comprehensions.dfy.expect index 88873fd8..887a3249 100644 --- a/Test/dafny0/Comprehensions.dfy.expect +++ b/Test/dafny0/Comprehensions.dfy.expect @@ -1,4 +1,4 @@ -Comprehensions.dfy(12,14): Error: assertion violation +Comprehensions.dfy(12,13): Error: assertion violation Execution trace: (0,0): anon0 (0,0): anon9_Then diff --git a/Test/dafny0/ComputationsLoop.dfy.expect b/Test/dafny0/ComputationsLoop.dfy.expect index 91dc2af9..84674030 100644 --- a/Test/dafny0/ComputationsLoop.dfy.expect +++ b/Test/dafny0/ComputationsLoop.dfy.expect @@ -1,8 +1,8 @@ -ComputationsLoop.dfy(7,3): Error: failure to decrease termination measure +ComputationsLoop.dfy(7,2): Error: failure to decrease termination measure Execution trace: (0,0): anon0 (0,0): anon4_Else -ComputationsLoop.dfy(12,26): Error: assertion violation +ComputationsLoop.dfy(12,25): Error: assertion violation Execution trace: (0,0): anon0 diff --git a/Test/dafny0/ComputationsLoop2.dfy.expect b/Test/dafny0/ComputationsLoop2.dfy.expect index 816cbd31..48fc618f 100644 --- a/Test/dafny0/ComputationsLoop2.dfy.expect +++ b/Test/dafny0/ComputationsLoop2.dfy.expect @@ -1,12 +1,12 @@ -ComputationsLoop2.dfy(6,3): Error: cannot prove termination; try supplying a decreases clause +ComputationsLoop2.dfy(6,2): Error: cannot prove termination; try supplying a decreases clause Execution trace: (0,0): anon0 (0,0): anon4_Else -ComputationsLoop2.dfy(11,3): Error: cannot prove termination; try supplying a decreases clause +ComputationsLoop2.dfy(11,2): Error: cannot prove termination; try supplying a decreases clause Execution trace: (0,0): anon0 (0,0): anon4_Else -ComputationsLoop2.dfy(16,26): Error: assertion violation +ComputationsLoop2.dfy(16,25): Error: assertion violation Execution trace: (0,0): anon0 diff --git a/Test/dafny0/ComputationsNeg.dfy.expect b/Test/dafny0/ComputationsNeg.dfy.expect index a6318087..598e9fa5 100644 --- a/Test/dafny0/ComputationsNeg.dfy.expect +++ b/Test/dafny0/ComputationsNeg.dfy.expect @@ -1,19 +1,19 @@ -ComputationsNeg.dfy(7,3): Error: failure to decrease termination measure +ComputationsNeg.dfy(7,2): Error: failure to decrease termination measure Execution trace: (0,0): anon0 (0,0): anon4_Else -ComputationsNeg.dfy(11,1): Error BP5003: A postcondition might not hold on this return path. -ComputationsNeg.dfy(10,17): Related location: This is the postcondition that might not hold. +ComputationsNeg.dfy(11,0): Error BP5003: A postcondition might not hold on this return path. +ComputationsNeg.dfy(10,16): Related location: This is the postcondition that might not hold. Execution trace: (0,0): anon0 -ComputationsNeg.dfy(23,1): Error BP5003: A postcondition might not hold on this return path. -ComputationsNeg.dfy(22,11): Related location: This is the postcondition that might not hold. +ComputationsNeg.dfy(23,0): Error BP5003: A postcondition might not hold on this return path. +ComputationsNeg.dfy(22,10): Related location: This is the postcondition that might not hold. Execution trace: (0,0): anon0 -ComputationsNeg.dfy(36,13): Error: assertion violation +ComputationsNeg.dfy(36,12): Error: assertion violation Execution trace: (0,0): anon0 -ComputationsNeg.dfy(45,13): Error: assertion violation +ComputationsNeg.dfy(45,12): Error: assertion violation Execution trace: (0,0): anon0 diff --git a/Test/dafny0/ControlStructures.dfy.expect b/Test/dafny0/ControlStructures.dfy.expect index 3f4dce92..5638bcbc 100644 --- a/Test/dafny0/ControlStructures.dfy.expect +++ b/Test/dafny0/ControlStructures.dfy.expect @@ -1,29 +1,29 @@ -ControlStructures.dfy(8,3): Error: missing case in case statement: Purple +ControlStructures.dfy(8,2): Error: missing case in case statement: Purple Execution trace: (0,0): anon0 (0,0): anon6_Else (0,0): anon7_Else (0,0): anon8_Then -ControlStructures.dfy(8,3): Error: missing case in case statement: Blue +ControlStructures.dfy(8,2): Error: missing case in case statement: Blue Execution trace: (0,0): anon0 (0,0): anon6_Else (0,0): anon7_Else (0,0): anon8_Else (0,0): anon9_Then -ControlStructures.dfy(17,3): Error: missing case in case statement: Purple +ControlStructures.dfy(17,2): Error: missing case in case statement: Purple Execution trace: (0,0): anon0 (0,0): anon6_Else (0,0): anon7_Else (0,0): anon8_Then -ControlStructures.dfy(46,5): Error: missing case in case statement: Red +ControlStructures.dfy(46,4): Error: missing case in case statement: Red Execution trace: (0,0): anon0 (0,0): anon8_Then (0,0): anon9_Else (0,0): anon10_Then -ControlStructures.dfy(54,3): Error: missing case in case statement: Red +ControlStructures.dfy(54,2): Error: missing case in case statement: Red Execution trace: (0,0): anon0 (0,0): anon9_Else @@ -31,11 +31,11 @@ Execution trace: (0,0): anon11_Else (0,0): anon12_Else (0,0): anon13_Then -ControlStructures.dfy(75,3): Error: alternative cases fail to cover all possibilties +ControlStructures.dfy(75,2): Error: alternative cases fail to cover all possibilties Execution trace: (0,0): anon0 (0,0): anon5_Else -ControlStructures.dfy(218,18): Error: assertion violation +ControlStructures.dfy(218,17): Error: assertion violation Execution trace: (0,0): anon0 ControlStructures.dfy(197,3): anon59_LoopHead @@ -51,7 +51,7 @@ Execution trace: (0,0): anon69_LoopBody ControlStructures.dfy(213,9): anon70_Else (0,0): anon71_Then -ControlStructures.dfy(235,21): Error: assertion violation +ControlStructures.dfy(235,20): Error: assertion violation Execution trace: (0,0): anon0 ControlStructures.dfy(197,3): anon59_LoopHead @@ -77,7 +77,7 @@ Execution trace: (0,0): anon38 (0,0): anon83_Then (0,0): anon52 -ControlStructures.dfy(238,30): Error: assertion violation +ControlStructures.dfy(238,29): Error: assertion violation Execution trace: (0,0): anon0 ControlStructures.dfy(197,3): anon59_LoopHead @@ -92,7 +92,7 @@ Execution trace: (0,0): anon84_Then (0,0): anon85_Then (0,0): anon56 -ControlStructures.dfy(241,17): Error: assertion violation +ControlStructures.dfy(241,16): Error: assertion violation Execution trace: (0,0): anon0 ControlStructures.dfy(197,3): anon59_LoopHead diff --git a/Test/dafny0/Corecursion.dfy.expect b/Test/dafny0/Corecursion.dfy.expect index 619a9c84..a6b3fdce 100644 --- a/Test/dafny0/Corecursion.dfy.expect +++ b/Test/dafny0/Corecursion.dfy.expect @@ -1,34 +1,34 @@ -Corecursion.dfy(17,13): Error: cannot prove termination; try supplying a decreases clause (note that only functions without side effects can be called co-recursively) +Corecursion.dfy(17,12): Error: cannot prove termination; try supplying a decreases clause (note that only functions without side effects can be called co-recursively) Execution trace: (0,0): anon0 (0,0): anon4_Else -Corecursion.dfy(23,13): Error: cannot prove termination; try supplying a decreases clause (note that only functions without any ensures clause can be called co-recursively) +Corecursion.dfy(23,12): Error: cannot prove termination; try supplying a decreases clause (note that only functions without any ensures clause can be called co-recursively) Execution trace: (0,0): anon0 (0,0): anon4_Else -Corecursion.dfy(58,5): Error: cannot prove termination; try supplying a decreases clause +Corecursion.dfy(58,4): Error: cannot prove termination; try supplying a decreases clause Execution trace: (0,0): anon0 (0,0): anon4_Else -Corecursion.dfy(71,16): Error: cannot prove termination; try supplying a decreases clause (note that calls cannot be co-recursive in this context) +Corecursion.dfy(71,15): Error: cannot prove termination; try supplying a decreases clause (note that calls cannot be co-recursive in this context) Execution trace: (0,0): anon0 (0,0): anon7_Else -Corecursion.dfy(93,15): Error: cannot prove termination; try supplying a decreases clause (note that a call can be co-recursive only if all intra-cluster calls are in non-destructive contexts) +Corecursion.dfy(93,14): Error: cannot prove termination; try supplying a decreases clause (note that a call can be co-recursive only if all intra-cluster calls are in non-destructive contexts) Execution trace: (0,0): anon0 (0,0): anon7_Else (0,0): anon8_Then -Corecursion.dfy(103,15): Error: cannot prove termination; try supplying a decreases clause (note that a call can be co-recursive only if all intra-cluster calls are in non-destructive contexts) +Corecursion.dfy(103,14): Error: cannot prove termination; try supplying a decreases clause (note that a call can be co-recursive only if all intra-cluster calls are in non-destructive contexts) Execution trace: (0,0): anon0 (0,0): anon7_Else (0,0): anon8_Then -Corecursion.dfy(148,13): Error: failure to decrease termination measure (note that a call can be co-recursive only if all intra-cluster calls are in non-destructive contexts) +Corecursion.dfy(148,12): Error: failure to decrease termination measure (note that a call can be co-recursive only if all intra-cluster calls are in non-destructive contexts) Execution trace: (0,0): anon0 (0,0): anon4_Else -Corecursion.dfy(161,13): Error: failure to decrease termination measure (note that a call can be co-recursive only if all intra-cluster calls are in non-destructive contexts) +Corecursion.dfy(161,12): Error: failure to decrease termination measure (note that a call can be co-recursive only if all intra-cluster calls are in non-destructive contexts) Execution trace: (0,0): anon0 (0,0): anon4_Else diff --git a/Test/dafny0/DTypes.dfy.expect b/Test/dafny0/DTypes.dfy.expect index 9b4288e9..76088e9b 100644 --- a/Test/dafny0/DTypes.dfy.expect +++ b/Test/dafny0/DTypes.dfy.expect @@ -1,27 +1,27 @@ -DTypes.dfy(182,3): Error BP5003: A postcondition might not hold on this return path. -DTypes.dfy(181,15): Related location: This is the postcondition that might not hold. +DTypes.dfy(182,2): Error BP5003: A postcondition might not hold on this return path. +DTypes.dfy(181,14): Related location: This is the postcondition that might not hold. Execution trace: (0,0): anon0 -DTypes.dfy(18,14): Error: assertion violation +DTypes.dfy(18,13): Error: assertion violation Execution trace: (0,0): anon0 -DTypes.dfy(56,18): Error: assertion violation +DTypes.dfy(56,17): Error: assertion violation Execution trace: (0,0): anon0 -DTypes.dfy(121,13): Error: assertion violation -DTypes.dfy(93,30): Related location +DTypes.dfy(121,12): Error: assertion violation +DTypes.dfy(93,29): Related location Execution trace: (0,0): anon0 -DTypes.dfy(127,13): Error: assertion violation -DTypes.dfy(93,20): Related location +DTypes.dfy(127,12): Error: assertion violation +DTypes.dfy(93,19): Related location Execution trace: (0,0): anon0 -DTypes.dfy(137,12): Error: assertion violation -DTypes.dfy(132,6): Related location -DTypes.dfy(93,20): Related location +DTypes.dfy(137,11): Error: assertion violation +DTypes.dfy(132,5): Related location +DTypes.dfy(93,19): Related location Execution trace: (0,0): anon0 -DTypes.dfy(158,12): Error: assertion violation +DTypes.dfy(158,11): Error: assertion violation Execution trace: (0,0): anon0 (0,0): anon5_Then diff --git a/Test/dafny0/Datatypes.dfy.expect b/Test/dafny0/Datatypes.dfy.expect index 4c0b1e96..7147ca60 100644 --- a/Test/dafny0/Datatypes.dfy.expect +++ b/Test/dafny0/Datatypes.dfy.expect @@ -1,43 +1,43 @@ -Datatypes.dfy(297,10): Error BP5003: A postcondition might not hold on this return path. -Datatypes.dfy(295,15): Related location: This is the postcondition that might not hold. +Datatypes.dfy(297,9): Error BP5003: A postcondition might not hold on this return path. +Datatypes.dfy(295,14): Related location: This is the postcondition that might not hold. Execution trace: (0,0): anon0 (0,0): anon13_Then (0,0): anon14_Else (0,0): anon15_Then (0,0): anon6 -Datatypes.dfy(298,12): Error: missing case in case statement: Appendix +Datatypes.dfy(298,11): Error: missing case in case statement: Appendix Execution trace: (0,0): anon0 (0,0): anon13_Then (0,0): anon14_Else (0,0): anon15_Else (0,0): anon16_Then -Datatypes.dfy(349,5): Error: missing case in case statement: Cons +Datatypes.dfy(349,4): Error: missing case in case statement: Cons Execution trace: (0,0): anon0 (0,0): anon7_Else (0,0): anon8_Then -Datatypes.dfy(349,5): Error: missing case in case statement: Nil +Datatypes.dfy(349,4): Error: missing case in case statement: Nil Execution trace: (0,0): anon0 (0,0): anon7_Else (0,0): anon8_Else (0,0): anon9_Then -Datatypes.dfy(356,8): Error: missing case in case statement: Cons +Datatypes.dfy(356,7): Error: missing case in case statement: Cons Execution trace: (0,0): anon0 (0,0): anon10_Else (0,0): anon11_Then (0,0): anon12_Then -Datatypes.dfy(356,8): Error: missing case in case statement: Nil +Datatypes.dfy(356,7): Error: missing case in case statement: Nil Execution trace: (0,0): anon0 (0,0): anon10_Else (0,0): anon11_Then (0,0): anon12_Else (0,0): anon13_Then -Datatypes.dfy(82,20): Error: assertion violation +Datatypes.dfy(82,19): Error: assertion violation Execution trace: (0,0): anon0 (0,0): anon20_Else @@ -47,23 +47,23 @@ Execution trace: (0,0): anon23_Then (0,0): anon24_Else (0,0): anon25_Then -Datatypes.dfy(170,16): Error: assertion violation +Datatypes.dfy(170,15): Error: assertion violation Execution trace: (0,0): anon0 (0,0): anon4_Then -Datatypes.dfy(172,16): Error: assertion violation +Datatypes.dfy(172,15): Error: assertion violation Execution trace: (0,0): anon0 (0,0): anon4_Else (0,0): anon5_Then -Datatypes.dfy(201,13): Error: destructor 'Car' can only be applied to datatype values constructed by 'XCons' +Datatypes.dfy(201,12): Error: destructor 'Car' can only be applied to datatype values constructed by 'XCons' Execution trace: (0,0): anon0 -Datatypes.dfy(204,17): Error: destructor 'Car' can only be applied to datatype values constructed by 'XCons' +Datatypes.dfy(204,16): Error: destructor 'Car' can only be applied to datatype values constructed by 'XCons' Execution trace: (0,0): anon0 (0,0): anon6_Then -Datatypes.dfy(225,17): Error: destructor 'c' can only be applied to datatype values constructed by 'T'' +Datatypes.dfy(225,16): Error: destructor 'c' can only be applied to datatype values constructed by 'T'' Execution trace: (0,0): anon0 (0,0): anon5_Then diff --git a/Test/dafny0/Definedness.dfy.expect b/Test/dafny0/Definedness.dfy.expect index af5b62b9..b5b015ad 100644 --- a/Test/dafny0/Definedness.dfy.expect +++ b/Test/dafny0/Definedness.dfy.expect @@ -1,87 +1,87 @@ -Definedness.dfy(11,7): Error: possible division by zero +Definedness.dfy(11,6): Error: possible division by zero Execution trace: (0,0): anon0 (0,0): anon4_Else -Definedness.dfy(18,16): Error: possible division by zero +Definedness.dfy(18,15): Error: possible division by zero Execution trace: (0,0): anon0 -Definedness.dfy(27,16): Error: target object may be null +Definedness.dfy(27,15): Error: target object may be null Execution trace: (0,0): anon0 -Definedness.dfy(28,21): Error: target object may be null +Definedness.dfy(28,20): Error: target object may be null Execution trace: (0,0): anon0 (0,0): anon3_Then -Definedness.dfy(29,17): Error: possible division by zero +Definedness.dfy(29,16): Error: possible division by zero Execution trace: (0,0): anon0 -Definedness.dfy(36,16): Error: target object may be null +Definedness.dfy(36,15): Error: target object may be null Execution trace: (0,0): anon0 -Definedness.dfy(45,16): Error: target object may be null +Definedness.dfy(45,15): Error: target object may be null Execution trace: (0,0): anon0 -Definedness.dfy(53,18): Error: target object may be null +Definedness.dfy(53,17): Error: target object may be null Execution trace: (0,0): anon0 -Definedness.dfy(54,3): Error BP5003: A postcondition might not hold on this return path. -Definedness.dfy(53,22): Related location: This is the postcondition that might not hold. +Definedness.dfy(54,2): Error BP5003: A postcondition might not hold on this return path. +Definedness.dfy(53,21): Related location: This is the postcondition that might not hold. Execution trace: (0,0): anon0 -Definedness.dfy(60,18): Error: target object may be null +Definedness.dfy(60,17): Error: target object may be null Execution trace: (0,0): anon0 -Definedness.dfy(61,3): Error BP5003: A postcondition might not hold on this return path. -Definedness.dfy(60,22): Related location: This is the postcondition that might not hold. +Definedness.dfy(61,2): Error BP5003: A postcondition might not hold on this return path. +Definedness.dfy(60,21): Related location: This is the postcondition that might not hold. Execution trace: (0,0): anon0 -Definedness.dfy(68,3): Error BP5003: A postcondition might not hold on this return path. -Definedness.dfy(67,22): Related location: This is the postcondition that might not hold. +Definedness.dfy(68,2): Error BP5003: A postcondition might not hold on this return path. +Definedness.dfy(67,21): Related location: This is the postcondition that might not hold. Execution trace: (0,0): anon0 -Definedness.dfy(88,7): Error: target object may be null +Definedness.dfy(88,6): Error: target object may be null Execution trace: (0,0): anon0 -Definedness.dfy(89,5): Error: possible violation of function precondition -Definedness.dfy(79,16): Related location +Definedness.dfy(89,4): Error: possible violation of function precondition +Definedness.dfy(79,15): Related location Execution trace: (0,0): anon0 -Definedness.dfy(89,10): Error: assignment may update an object not in the enclosing context's modifies clause +Definedness.dfy(89,9): Error: assignment may update an object not in the enclosing context's modifies clause Execution trace: (0,0): anon0 -Definedness.dfy(89,10): Error: target object may be null +Definedness.dfy(89,9): Error: target object may be null Execution trace: (0,0): anon0 -Definedness.dfy(90,10): Error: possible violation of function precondition -Definedness.dfy(79,16): Related location +Definedness.dfy(90,9): Error: possible violation of function precondition +Definedness.dfy(79,15): Related location Execution trace: (0,0): anon0 -Definedness.dfy(95,14): Error: possible division by zero +Definedness.dfy(95,13): Error: possible division by zero Execution trace: (0,0): anon0 -Definedness.dfy(95,23): Error: possible division by zero +Definedness.dfy(95,22): Error: possible division by zero Execution trace: (0,0): anon0 -Definedness.dfy(96,15): Error: possible division by zero +Definedness.dfy(96,14): Error: possible division by zero Execution trace: (0,0): anon0 -Definedness.dfy(101,12): Error: possible division by zero +Definedness.dfy(101,11): Error: possible division by zero Execution trace: (0,0): anon0 -Definedness.dfy(108,15): Error: possible division by zero +Definedness.dfy(108,14): Error: possible division by zero Execution trace: Definedness.dfy(108,5): anon7_LoopHead (0,0): anon7_LoopBody Definedness.dfy(108,5): anon8_Else -Definedness.dfy(117,23): Error: possible violation of function precondition -Definedness.dfy(79,16): Related location +Definedness.dfy(117,22): Error: possible violation of function precondition +Definedness.dfy(79,15): Related location Execution trace: (0,0): anon0 Definedness.dfy(116,5): anon12_LoopHead (0,0): anon12_LoopBody (0,0): anon13_Then -Definedness.dfy(123,17): Error: possible violation of function precondition -Definedness.dfy(79,16): Related location +Definedness.dfy(123,16): Error: possible violation of function precondition +Definedness.dfy(79,15): Related location Execution trace: (0,0): anon0 Definedness.dfy(116,5): anon12_LoopHead @@ -91,30 +91,30 @@ Execution trace: Definedness.dfy(122,5): anon15_LoopHead (0,0): anon15_LoopBody (0,0): anon16_Then -Definedness.dfy(133,17): Error: possible violation of function precondition -Definedness.dfy(79,16): Related location +Definedness.dfy(133,16): Error: possible violation of function precondition +Definedness.dfy(79,15): Related location Execution trace: (0,0): anon0 Definedness.dfy(132,5): anon6_LoopHead (0,0): anon6_LoopBody (0,0): anon7_Then -Definedness.dfy(133,22): Error BP5004: This loop invariant might not hold on entry. +Definedness.dfy(133,21): Error BP5004: This loop invariant might not hold on entry. Execution trace: (0,0): anon0 -Definedness.dfy(134,17): Error: possible violation of function precondition -Definedness.dfy(79,16): Related location +Definedness.dfy(134,16): Error: possible violation of function precondition +Definedness.dfy(79,15): Related location Execution trace: (0,0): anon0 Definedness.dfy(132,5): anon6_LoopHead (0,0): anon6_LoopBody (0,0): anon7_Then -Definedness.dfy(143,15): Error: possible division by zero +Definedness.dfy(143,14): Error: possible division by zero Execution trace: (0,0): anon0 Definedness.dfy(143,5): anon8_LoopHead (0,0): anon8_LoopBody Definedness.dfy(143,5): anon9_Else -Definedness.dfy(162,15): Error: possible division by zero +Definedness.dfy(162,14): Error: possible division by zero Execution trace: (0,0): anon0 Definedness.dfy(156,5): anon16_LoopHead @@ -126,11 +126,11 @@ Execution trace: Definedness.dfy(162,5): anon20_LoopHead (0,0): anon20_LoopBody Definedness.dfy(162,5): anon21_Else -Definedness.dfy(175,28): Error BP5004: This loop invariant might not hold on entry. +Definedness.dfy(175,27): Error BP5004: This loop invariant might not hold on entry. Execution trace: (0,0): anon0 -Definedness.dfy(181,17): Error: possible violation of function precondition -Definedness.dfy(79,16): Related location +Definedness.dfy(181,16): Error: possible violation of function precondition +Definedness.dfy(79,15): Related location Execution trace: (0,0): anon0 Definedness.dfy(173,5): anon18_LoopHead @@ -142,32 +142,32 @@ Execution trace: (0,0): anon22_Then (0,0): anon23_Then (0,0): anon11 -Definedness.dfy(196,19): Error: possible division by zero +Definedness.dfy(196,18): Error: possible division by zero Execution trace: (0,0): anon0 Definedness.dfy(194,5): anon6_LoopHead (0,0): anon6_LoopBody (0,0): anon7_Then -Definedness.dfy(196,23): Error BP5004: This loop invariant might not hold on entry. +Definedness.dfy(196,22): Error BP5004: This loop invariant might not hold on entry. Execution trace: (0,0): anon0 -Definedness.dfy(196,28): Error: possible division by zero +Definedness.dfy(196,27): Error: possible division by zero Execution trace: (0,0): anon0 Definedness.dfy(194,5): anon6_LoopHead (0,0): anon6_LoopBody (0,0): anon7_Then -Definedness.dfy(215,10): Error BP5003: A postcondition might not hold on this return path. -Definedness.dfy(217,46): Related location: This is the postcondition that might not hold. +Definedness.dfy(215,9): Error BP5003: A postcondition might not hold on this return path. +Definedness.dfy(217,45): Related location: This is the postcondition that might not hold. Execution trace: (0,0): anon0 (0,0): anon4_Else -Definedness.dfy(224,22): Error: target object may be null +Definedness.dfy(224,21): Error: target object may be null Execution trace: (0,0): anon0 (0,0): anon4_Then -Definedness.dfy(237,10): Error BP5003: A postcondition might not hold on this return path. -Definedness.dfy(240,24): Related location: This is the postcondition that might not hold. +Definedness.dfy(237,9): Error BP5003: A postcondition might not hold on this return path. +Definedness.dfy(240,23): Related location: This is the postcondition that might not hold. Execution trace: (0,0): anon0 (0,0): anon4_Else diff --git a/Test/dafny0/DeterministicPick.dfy.expect b/Test/dafny0/DeterministicPick.dfy.expect index 0999294e..aef97ebd 100644 --- a/Test/dafny0/DeterministicPick.dfy.expect +++ b/Test/dafny0/DeterministicPick.dfy.expect @@ -1,4 +1,4 @@ -DeterministicPick.dfy(13,5): Error: to be compilable, the value of a let-such-that expression must be uniquely determined +DeterministicPick.dfy(13,4): Error: to be compilable, the value of a let-such-that expression must be uniquely determined Execution trace: (0,0): anon0 (0,0): anon4_Else diff --git a/Test/dafny0/DiamondImports.dfy.expect b/Test/dafny0/DiamondImports.dfy.expect index e9e8c2b9..1acca075 100644 --- a/Test/dafny0/DiamondImports.dfy.expect +++ b/Test/dafny0/DiamondImports.dfy.expect @@ -1,12 +1,12 @@ -DiamondImports.dfy(34,16): Error: assertion violation +DiamondImports.dfy(34,15): Error: assertion violation Execution trace: (0,0): anon0 -DiamondImports.dfy(50,16): Error: assertion violation +DiamondImports.dfy(50,15): Error: assertion violation Execution trace: (0,0): anon0 (0,0): anon3_Then (0,0): anon2 -DiamondImports.dfy(101,16): Error: assertion violation +DiamondImports.dfy(101,15): Error: assertion violation Execution trace: (0,0): anon0 (0,0): anon7_Then @@ -14,7 +14,7 @@ Execution trace: (0,0): anon8_Then (0,0): anon9_Then (0,0): anon6 -DiamondImports.dfy(120,16): Error: assertion violation +DiamondImports.dfy(120,15): Error: assertion violation Execution trace: (0,0): anon0 (0,0): anon9_Then @@ -25,7 +25,7 @@ Execution trace: (0,0): anon6 (0,0): anon12_Then (0,0): anon8 -DiamondImports.dfy(140,26): Error: assertion violation +DiamondImports.dfy(140,25): Error: assertion violation Execution trace: (0,0): anon0 diff --git a/Test/dafny0/Fuel.dfy.expect b/Test/dafny0/Fuel.dfy.expect index 4c180a9c..90fe877d 100644 --- a/Test/dafny0/Fuel.dfy.expect +++ b/Test/dafny0/Fuel.dfy.expect @@ -1,94 +1,94 @@ -Fuel.dfy(17,23): Error: assertion violation +Fuel.dfy(17,22): Error: assertion violation Execution trace: (0,0): anon0 -Fuel.dfy(65,28): Error: assertion violation +Fuel.dfy(65,27): Error: assertion violation Execution trace: (0,0): anon0 (0,0): anon6_Else -Fuel.dfy(69,28): Error: assertion violation +Fuel.dfy(69,27): Error: assertion violation Execution trace: (0,0): anon0 (0,0): anon6_Then (0,0): anon7_Then -Fuel.dfy(92,23): Error: assertion violation +Fuel.dfy(92,22): Error: assertion violation Execution trace: (0,0): anon0 -Fuel.dfy(94,23): Error: assertion violation +Fuel.dfy(94,22): Error: assertion violation Execution trace: (0,0): anon0 -Fuel.dfy(120,23): Error: assertion violation +Fuel.dfy(120,22): Error: assertion violation Execution trace: (0,0): anon0 -Fuel.dfy(122,23): Error: assertion violation +Fuel.dfy(122,22): Error: assertion violation Execution trace: (0,0): anon0 -Fuel.dfy(129,39): Error: assertion violation +Fuel.dfy(129,38): Error: assertion violation Execution trace: (0,0): anon0 -Fuel.dfy(132,27): Error: assertion violation +Fuel.dfy(132,26): Error: assertion violation Execution trace: (0,0): anon0 (0,0): anon3_Then -Fuel.dfy(133,27): Error: assertion violation +Fuel.dfy(133,26): Error: assertion violation Execution trace: (0,0): anon0 (0,0): anon3_Then -Fuel.dfy(157,23): Error: assertion violation +Fuel.dfy(157,22): Error: assertion violation Execution trace: (0,0): anon0 (0,0): anon10_Else (0,0): anon9 -Fuel.dfy(200,56): Error: assertion violation +Fuel.dfy(200,55): Error: assertion violation Execution trace: (0,0): anon0 -Fuel.dfy(245,23): Error: assertion violation +Fuel.dfy(245,22): Error: assertion violation Execution trace: (0,0): anon0 -Fuel.dfy(247,23): Error: assertion violation +Fuel.dfy(247,22): Error: assertion violation Execution trace: (0,0): anon0 -Fuel.dfy(280,27): Error: assertion violation +Fuel.dfy(280,26): Error: assertion violation Execution trace: (0,0): anon0 (0,0): anon7_Then -Fuel.dfy(335,27): Error: possible violation of function precondition -Fuel.dfy(324,22): Related location +Fuel.dfy(335,26): Error: possible violation of function precondition +Fuel.dfy(324,21): Related location Execution trace: (0,0): anon0 (0,0): anon7_Else (0,0): anon8_Then -Fuel.dfy(335,50): Error: destructor 't' can only be applied to datatype values constructed by 'VTuple' +Fuel.dfy(335,49): Error: destructor 't' can only be applied to datatype values constructed by 'VTuple' Execution trace: (0,0): anon0 (0,0): anon7_Else (0,0): anon8_Then -Fuel.dfy(335,51): Error: index out of range +Fuel.dfy(335,50): Error: index out of range Execution trace: (0,0): anon0 (0,0): anon7_Else (0,0): anon8_Then -Fuel.dfy(336,39): Error: index out of range +Fuel.dfy(336,38): Error: index out of range Execution trace: (0,0): anon0 (0,0): anon7_Else (0,0): anon8_Then -Fuel.dfy(336,43): Error: destructor 'u' can only be applied to datatype values constructed by 'VUint64' +Fuel.dfy(336,42): Error: destructor 'u' can only be applied to datatype values constructed by 'VUint64' Execution trace: (0,0): anon0 (0,0): anon7_Else (0,0): anon8_Then -Fuel.dfy(346,43): Error: destructor 'u' can only be applied to datatype values constructed by 'VUint64' +Fuel.dfy(346,42): Error: destructor 'u' can only be applied to datatype values constructed by 'VUint64' Execution trace: (0,0): anon0 (0,0): anon7_Else (0,0): anon8_Then -Fuel.dfy(397,23): Error: assertion violation +Fuel.dfy(397,22): Error: assertion violation Execution trace: (0,0): anon0 -Fuel.dfy(398,23): Error: assertion violation +Fuel.dfy(398,22): Error: assertion violation Execution trace: (0,0): anon0 -Fuel.dfy(407,39): Error: assertion violation +Fuel.dfy(407,38): Error: assertion violation Execution trace: (0,0): anon0 diff --git a/Test/dafny0/FunctionSpecifications.dfy.expect b/Test/dafny0/FunctionSpecifications.dfy.expect index 9f76313a..078afaef 100644 --- a/Test/dafny0/FunctionSpecifications.dfy.expect +++ b/Test/dafny0/FunctionSpecifications.dfy.expect @@ -1,5 +1,5 @@ -FunctionSpecifications.dfy(29,10): Error BP5003: A postcondition might not hold on this return path. -FunctionSpecifications.dfy(31,13): Related location: This is the postcondition that might not hold. +FunctionSpecifications.dfy(29,9): Error BP5003: A postcondition might not hold on this return path. +FunctionSpecifications.dfy(31,12): Related location: This is the postcondition that might not hold. Execution trace: (0,0): anon0 (0,0): anon10_Else @@ -7,64 +7,64 @@ Execution trace: (0,0): anon12_Then (0,0): anon13_Else (0,0): anon9 -FunctionSpecifications.dfy(38,10): Error BP5003: A postcondition might not hold on this return path. -FunctionSpecifications.dfy(40,24): Related location: This is the postcondition that might not hold. +FunctionSpecifications.dfy(38,9): Error BP5003: A postcondition might not hold on this return path. +FunctionSpecifications.dfy(40,23): Related location: This is the postcondition that might not hold. Execution trace: (0,0): anon0 (0,0): anon15_Else (0,0): anon18_Else (0,0): anon19_Then (0,0): anon14 -FunctionSpecifications.dfy(53,11): Error: cannot prove termination; try supplying a decreases clause +FunctionSpecifications.dfy(53,10): Error: cannot prove termination; try supplying a decreases clause Execution trace: (0,0): anon0 (0,0): anon11_Then (0,0): anon5 -FunctionSpecifications.dfy(59,10): Error BP5003: A postcondition might not hold on this return path. -FunctionSpecifications.dfy(60,22): Related location: This is the postcondition that might not hold. +FunctionSpecifications.dfy(59,9): Error BP5003: A postcondition might not hold on this return path. +FunctionSpecifications.dfy(60,21): Related location: This is the postcondition that might not hold. Execution trace: (0,0): anon0 (0,0): anon7_Else -FunctionSpecifications.dfy(108,23): Error: assertion violation +FunctionSpecifications.dfy(108,22): Error: assertion violation Execution trace: (0,0): anon0 -FunctionSpecifications.dfy(111,23): Error: assertion violation +FunctionSpecifications.dfy(111,22): Error: assertion violation Execution trace: (0,0): anon0 -FunctionSpecifications.dfy(126,27): Error: assertion violation +FunctionSpecifications.dfy(126,26): Error: assertion violation Execution trace: (0,0): anon0 (0,0): anon3_Then -FunctionSpecifications.dfy(130,27): Error: assertion violation +FunctionSpecifications.dfy(130,26): Error: assertion violation Execution trace: (0,0): anon0 (0,0): anon3_Else -FunctionSpecifications.dfy(158,3): Error: cannot prove termination; try supplying a decreases clause +FunctionSpecifications.dfy(158,2): Error: cannot prove termination; try supplying a decreases clause Execution trace: (0,0): anon0 (0,0): anon4_Else -FunctionSpecifications.dfy(167,11): Error: cannot prove termination; try supplying a decreases clause +FunctionSpecifications.dfy(167,10): Error: cannot prove termination; try supplying a decreases clause Execution trace: (0,0): anon0 (0,0): anon4_Else -FunctionSpecifications.dfy(135,20): Error BP5003: A postcondition might not hold on this return path. -FunctionSpecifications.dfy(137,29): Related location: This is the postcondition that might not hold. +FunctionSpecifications.dfy(135,19): Error BP5003: A postcondition might not hold on this return path. +FunctionSpecifications.dfy(137,28): Related location: This is the postcondition that might not hold. Execution trace: (0,0): anon0 (0,0): anon4_Else -FunctionSpecifications.dfy(146,3): Error: failure to decrease termination measure +FunctionSpecifications.dfy(146,2): Error: failure to decrease termination measure Execution trace: (0,0): anon0 (0,0): anon4_Else -FunctionSpecifications.dfy(153,3): Error: failure to decrease termination measure +FunctionSpecifications.dfy(153,2): Error: failure to decrease termination measure Execution trace: (0,0): anon0 (0,0): anon4_Else -FunctionSpecifications.dfy(174,3): Error: cannot prove termination; try supplying a decreases clause +FunctionSpecifications.dfy(174,2): Error: cannot prove termination; try supplying a decreases clause Execution trace: (0,0): anon0 (0,0): anon4_Else -FunctionSpecifications.dfy(171,20): Error: cannot prove termination; try supplying a decreases clause +FunctionSpecifications.dfy(171,19): Error: cannot prove termination; try supplying a decreases clause Execution trace: (0,0): anon0 diff --git a/Test/dafny0/IMaps.dfy.expect b/Test/dafny0/IMaps.dfy.expect index c2da9505..28ca8ca3 100644 --- a/Test/dafny0/IMaps.dfy.expect +++ b/Test/dafny0/IMaps.dfy.expect @@ -1,4 +1,4 @@ -IMaps.dfy(52,8): Error: element may not be in domain +IMaps.dfy(52,7): Error: element may not be in domain Execution trace: (0,0): anon0 (0,0): anon5_Then diff --git a/Test/dafny0/Include.dfy.expect b/Test/dafny0/Include.dfy.expect index 0921cec9..d4543afe 100644 --- a/Test/dafny0/Include.dfy.expect +++ b/Test/dafny0/Include.dfy.expect @@ -1,13 +1,13 @@ -Include.dfy(19,19): Error BP5003: A postcondition might not hold on this return path. -Includee.dfy(17,20): Related location: This is the postcondition that might not hold. +Include.dfy(19,18): Error BP5003: A postcondition might not hold on this return path. +Includee.dfy(17,19): Related location: This is the postcondition that might not hold. Execution trace: (0,0): anon0 (0,0): anon4_Else -Includee.dfy[Concrete](22,16): Error: assertion violation +Includee.dfy[Concrete](22,15): Error: assertion violation Execution trace: (0,0): anon0 -Include.dfy(27,7): Error BP5003: A postcondition might not hold on this return path. -Includee.dfy[Concrete](20,15): Related location: This is the postcondition that might not hold. +Include.dfy(27,6): Error BP5003: A postcondition might not hold on this return path. +Includee.dfy[Concrete](20,14): Related location: This is the postcondition that might not hold. Execution trace: (0,0): anon0 (0,0): anon6_Then diff --git a/Test/dafny0/Includee.dfy.expect b/Test/dafny0/Includee.dfy.expect index e0f0689c..ce61e32a 100644 --- a/Test/dafny0/Includee.dfy.expect +++ b/Test/dafny0/Includee.dfy.expect @@ -1,12 +1,12 @@ -Includee.dfy(21,3): Error BP5003: A postcondition might not hold on this return path. -Includee.dfy(20,15): Related location: This is the postcondition that might not hold. +Includee.dfy(21,2): Error BP5003: A postcondition might not hold on this return path. +Includee.dfy(20,14): Related location: This is the postcondition that might not hold. Execution trace: (0,0): anon0 -Includee.dfy(24,18): Error: assertion violation +Includee.dfy(24,17): Error: assertion violation Execution trace: (0,0): anon0 -Includee.dfy(6,1): Error BP5003: A postcondition might not hold on this return path. -Includee.dfy(5,13): Related location: This is the postcondition that might not hold. +Includee.dfy(6,0): Error BP5003: A postcondition might not hold on this return path. +Includee.dfy(5,12): Related location: This is the postcondition that might not hold. Execution trace: (0,0): anon0 diff --git a/Test/dafny0/IndexIntoUpdate.dfy.expect b/Test/dafny0/IndexIntoUpdate.dfy.expect index 3423a20b..2db3aa0a 100644 --- a/Test/dafny0/IndexIntoUpdate.dfy.expect +++ b/Test/dafny0/IndexIntoUpdate.dfy.expect @@ -1,4 +1,4 @@ -IndexIntoUpdate.dfy(7,19): Error: assertion violation +IndexIntoUpdate.dfy(7,18): Error: assertion violation Execution trace: (0,0): anon0 (0,0): anon3_Then diff --git a/Test/dafny0/InductivePredicates.dfy.expect b/Test/dafny0/InductivePredicates.dfy.expect index b09b7903..ccf30643 100644 --- a/Test/dafny0/InductivePredicates.dfy.expect +++ b/Test/dafny0/InductivePredicates.dfy.expect @@ -1,8 +1,8 @@ -InductivePredicates.dfy(64,10): Error: assertion violation +InductivePredicates.dfy(64,9): Error: assertion violation Execution trace: (0,0): anon0 (0,0): anon3_Then -InductivePredicates.dfy(76,11): Error: assertion violation +InductivePredicates.dfy(76,10): Error: assertion violation Execution trace: (0,0): anon0 diff --git a/Test/dafny0/Inverses.dfy.expect b/Test/dafny0/Inverses.dfy.expect index a04f21dc..29c67e5d 100644 --- a/Test/dafny0/Inverses.dfy.expect +++ b/Test/dafny0/Inverses.dfy.expect @@ -1,10 +1,10 @@ -Inverses.dfy(70,1): Error BP5003: A postcondition might not hold on this return path. -Inverses.dfy(69,11): Related location: This is the postcondition that might not hold. +Inverses.dfy(70,0): Error BP5003: A postcondition might not hold on this return path. +Inverses.dfy(69,10): Related location: This is the postcondition that might not hold. Execution trace: (0,0): anon0 (0,0): anon6_Else -Inverses.dfy(83,1): Error BP5003: A postcondition might not hold on this return path. -Inverses.dfy(82,11): Related location: This is the postcondition that might not hold. +Inverses.dfy(83,0): Error BP5003: A postcondition might not hold on this return path. +Inverses.dfy(82,10): Related location: This is the postcondition that might not hold. Execution trace: (0,0): anon0 (0,0): anon9_Else diff --git a/Test/dafny0/Iterators.dfy.expect b/Test/dafny0/Iterators.dfy.expect index f0c6e400..d9129e3e 100644 --- a/Test/dafny0/Iterators.dfy.expect +++ b/Test/dafny0/Iterators.dfy.expect @@ -1,55 +1,55 @@ -Iterators.dfy(251,10): Error: failure to decrease termination measure +Iterators.dfy(251,9): Error: failure to decrease termination measure Execution trace: (0,0): anon0 (0,0): anon5_Else (0,0): anon6_Else -Iterators.dfy(274,10): Error: failure to decrease termination measure +Iterators.dfy(274,9): Error: failure to decrease termination measure Execution trace: (0,0): anon0 (0,0): anon5_Else (0,0): anon6_Else -Iterators.dfy(284,32): Error: failure to decrease termination measure +Iterators.dfy(284,31): Error: failure to decrease termination measure Execution trace: (0,0): anon0 -Iterators.dfy(296,10): Error: cannot prove termination; try supplying a decreases clause +Iterators.dfy(296,9): Error: cannot prove termination; try supplying a decreases clause Execution trace: (0,0): anon0 (0,0): anon5_Else (0,0): anon6_Else -Iterators.dfy(317,10): Error: cannot prove termination; try supplying a decreases clause +Iterators.dfy(317,9): Error: cannot prove termination; try supplying a decreases clause Execution trace: (0,0): anon0 (0,0): anon5_Else (0,0): anon6_Else -Iterators.dfy(326,32): Error: cannot prove termination; try supplying a decreases clause +Iterators.dfy(326,31): Error: cannot prove termination; try supplying a decreases clause Execution trace: (0,0): anon0 -Iterators.dfy(343,10): Error: failure to decrease termination measure +Iterators.dfy(343,9): Error: failure to decrease termination measure Execution trace: (0,0): anon0 (0,0): anon5_Else (0,0): anon6_Else -Iterators.dfy(353,32): Error: cannot prove termination; try supplying a decreases clause +Iterators.dfy(353,31): Error: cannot prove termination; try supplying a decreases clause Execution trace: (0,0): anon0 -Iterators.dfy(370,10): Error: failure to decrease termination measure +Iterators.dfy(370,9): Error: failure to decrease termination measure Execution trace: (0,0): anon0 (0,0): anon5_Else (0,0): anon6_Else -Iterators.dfy(103,22): Error: assertion violation +Iterators.dfy(103,21): Error: assertion violation Execution trace: (0,0): anon0 -Iterators.dfy(106,14): Error: assertion violation +Iterators.dfy(106,13): Error: assertion violation Execution trace: (0,0): anon0 (0,0): anon4_Then (0,0): anon3 -Iterators.dfy(177,28): Error: assertion violation +Iterators.dfy(177,27): Error: assertion violation Execution trace: (0,0): anon0 (0,0): anon15_Then -Iterators.dfy(208,7): Error: an assignment to _new is only allowed to shrink the set +Iterators.dfy(208,6): Error: an assignment to _new is only allowed to shrink the set Execution trace: (0,0): anon0 Iterators.dfy(197,3): anon16_LoopHead @@ -57,7 +57,7 @@ Execution trace: Iterators.dfy(197,3): anon17_Else Iterators.dfy(197,3): anon19_Else (0,0): anon20_Then -Iterators.dfy(212,21): Error: assertion violation +Iterators.dfy(212,20): Error: assertion violation Execution trace: (0,0): anon0 Iterators.dfy(197,3): anon16_LoopHead @@ -65,8 +65,8 @@ Execution trace: Iterators.dfy(197,3): anon17_Else Iterators.dfy(197,3): anon19_Else (0,0): anon21_Then -Iterators.dfy(40,22): Error BP5002: A precondition for this call might not hold. -Iterators.dfy(4,10): Related location: This is the precondition that might not hold. +Iterators.dfy(40,21): Error BP5002: A precondition for this call might not hold. +Iterators.dfy(4,9): Related location: This is the precondition that might not hold. Execution trace: (0,0): anon0 (0,0): anon35_Then @@ -74,24 +74,24 @@ Execution trace: (0,0): anon36_Then (0,0): anon5 (0,0): anon37_Then -Iterators.dfy(89,14): Error: assertion violation +Iterators.dfy(89,13): Error: assertion violation Execution trace: (0,0): anon0 -Iterators.dfy(119,16): Error: assertion violation +Iterators.dfy(119,15): Error: assertion violation Execution trace: (0,0): anon0 (0,0): anon3_Else -Iterators.dfy(150,16): Error: assertion violation +Iterators.dfy(150,15): Error: assertion violation Execution trace: (0,0): anon0 (0,0): anon4_Else -Iterators.dfy(155,24): Error BP5002: A precondition for this call might not hold. -Iterators.dfy(125,10): Related location: This is the precondition that might not hold. +Iterators.dfy(155,23): Error BP5002: A precondition for this call might not hold. +Iterators.dfy(125,9): Related location: This is the precondition that might not hold. Execution trace: (0,0): anon0 (0,0): anon4_Then (0,0): anon3 -Iterators.dfy(234,21): Error: assertion violation +Iterators.dfy(234,20): Error: assertion violation Execution trace: (0,0): anon0 Iterators.dfy(225,3): anon14_LoopHead diff --git a/Test/dafny0/LetExpr.dfy.expect b/Test/dafny0/LetExpr.dfy.expect index 66dc2764..f0f51274 100644 --- a/Test/dafny0/LetExpr.dfy.expect +++ b/Test/dafny0/LetExpr.dfy.expect @@ -1,35 +1,35 @@ -LetExpr.dfy(109,23): Error: assertion violation +LetExpr.dfy(109,22): Error: assertion violation Execution trace: (0,0): anon0 (0,0): anon11_Then -LetExpr.dfy(9,12): Error: assertion violation +LetExpr.dfy(9,11): Error: assertion violation Execution trace: (0,0): anon0 -LetExpr.dfy(254,19): Error: value assigned to a nat must be non-negative +LetExpr.dfy(254,18): Error: value assigned to a nat must be non-negative Execution trace: (0,0): anon0 (0,0): anon5_Then -LetExpr.dfy(257,19): Error: value assigned to a nat must be non-negative +LetExpr.dfy(257,18): Error: value assigned to a nat must be non-negative Execution trace: (0,0): anon0 (0,0): anon6_Then -LetExpr.dfy(259,24): Error: value assigned to a nat must be non-negative +LetExpr.dfy(259,23): Error: value assigned to a nat must be non-negative Execution trace: (0,0): anon0 (0,0): anon6_Else -LetExpr.dfy(288,14): Error: RHS is not certain to look like the pattern 'Agnes' +LetExpr.dfy(288,13): Error: RHS is not certain to look like the pattern 'Agnes' Execution trace: (0,0): anon0 (0,0): anon3_Else -LetExpr.dfy(305,42): Error: value assigned to a nat must be non-negative +LetExpr.dfy(305,41): Error: value assigned to a nat must be non-negative Execution trace: (0,0): anon0 (0,0): anon7_Else -LetExpr.dfy(307,12): Error: assertion violation +LetExpr.dfy(307,11): Error: assertion violation Execution trace: (0,0): anon0 (0,0): anon7_Else -LetExpr.dfy(317,12): Error: to be compilable, the value of a let-such-that expression must be uniquely determined +LetExpr.dfy(317,11): Error: to be compilable, the value of a let-such-that expression must be uniquely determined Execution trace: (0,0): anon0 (0,0): anon10_Then diff --git a/Test/dafny0/LhsDuplicates.dfy.expect b/Test/dafny0/LhsDuplicates.dfy.expect index a864390f..d6689047 100644 --- a/Test/dafny0/LhsDuplicates.dfy.expect +++ b/Test/dafny0/LhsDuplicates.dfy.expect @@ -1,27 +1,27 @@ -LhsDuplicates.dfy(18,10): Error: left-hand sides for different forall-statement bound variables may refer to the same location +LhsDuplicates.dfy(18,9): Error: left-hand sides for different forall-statement bound variables may refer to the same location Execution trace: (0,0): anon0 (0,0): anon16_Else (0,0): anon18_Else (0,0): anon21_Then (0,0): anon13 -LhsDuplicates.dfy(34,12): Error: left-hand sides for different forall-statement bound variables may refer to the same location +LhsDuplicates.dfy(34,11): Error: left-hand sides for different forall-statement bound variables may refer to the same location Execution trace: (0,0): anon0 (0,0): anon16_Else (0,0): anon18_Else (0,0): anon21_Then (0,0): anon13 -LhsDuplicates.dfy(42,12): Error: when left-hand sides 1 and 3 refer to the same location, they must be assigned the same value +LhsDuplicates.dfy(42,11): Error: when left-hand sides 1 and 3 refer to the same location, they must be assigned the same value Execution trace: (0,0): anon0 -LhsDuplicates.dfy(51,18): Error: when left-hand sides 0 and 2 refer to the same location, they must be assigned the same value +LhsDuplicates.dfy(51,17): Error: when left-hand sides 0 and 2 refer to the same location, they must be assigned the same value Execution trace: (0,0): anon0 -LhsDuplicates.dfy(60,16): Error: when left-hand sides 1 and 2 may refer to the same location, they must be assigned the same value +LhsDuplicates.dfy(60,15): Error: when left-hand sides 1 and 2 may refer to the same location, they must be assigned the same value Execution trace: (0,0): anon0 -LhsDuplicates.dfy(69,20): Error: when left-hand sides 1 and 2 refer to the same location, they must be assigned the same value +LhsDuplicates.dfy(69,19): Error: when left-hand sides 1 and 2 refer to the same location, they must be assigned the same value Execution trace: (0,0): anon0 diff --git a/Test/dafny0/LoopModifies.dfy.expect b/Test/dafny0/LoopModifies.dfy.expect index 682975fb..a7ded8a4 100644 --- a/Test/dafny0/LoopModifies.dfy.expect +++ b/Test/dafny0/LoopModifies.dfy.expect @@ -1,38 +1,38 @@ -LoopModifies.dfy(8,5): Error: assignment may update an array element not in the enclosing context's modifies clause +LoopModifies.dfy(8,4): Error: assignment may update an array element not in the enclosing context's modifies clause Execution trace: (0,0): anon0 -LoopModifies.dfy(19,8): Error: assignment may update an array element not in the enclosing context's modifies clause +LoopModifies.dfy(19,7): Error: assignment may update an array element not in the enclosing context's modifies clause Execution trace: (0,0): anon0 LoopModifies.dfy(16,4): anon8_LoopHead (0,0): anon8_LoopBody LoopModifies.dfy(16,4): anon9_Else LoopModifies.dfy(16,4): anon11_Else -LoopModifies.dfy(48,8): Error: assignment may update an array element not in the enclosing context's modifies clause +LoopModifies.dfy(48,7): Error: assignment may update an array element not in the enclosing context's modifies clause Execution trace: (0,0): anon0 LoopModifies.dfy(44,4): anon8_LoopHead (0,0): anon8_LoopBody LoopModifies.dfy(44,4): anon9_Else LoopModifies.dfy(44,4): anon11_Else -LoopModifies.dfy(63,8): Error: assignment may update an array element not in the enclosing context's modifies clause +LoopModifies.dfy(63,7): Error: assignment may update an array element not in the enclosing context's modifies clause Execution trace: (0,0): anon0 LoopModifies.dfy(59,4): anon9_LoopHead (0,0): anon9_LoopBody LoopModifies.dfy(59,4): anon10_Else LoopModifies.dfy(59,4): anon12_Else -LoopModifies.dfy(76,4): Error: loop modifies clause may violate context's modifies clause +LoopModifies.dfy(76,3): Error: loop modifies clause may violate context's modifies clause Execution trace: (0,0): anon0 -LoopModifies.dfy(100,8): Error: assignment may update an array element not in the enclosing context's modifies clause +LoopModifies.dfy(100,7): Error: assignment may update an array element not in the enclosing context's modifies clause Execution trace: (0,0): anon0 LoopModifies.dfy(92,4): anon8_LoopHead (0,0): anon8_LoopBody LoopModifies.dfy(92,4): anon9_Else LoopModifies.dfy(92,4): anon11_Else -LoopModifies.dfy(148,11): Error: assignment may update an array element not in the enclosing context's modifies clause +LoopModifies.dfy(148,10): Error: assignment may update an array element not in the enclosing context's modifies clause Execution trace: (0,0): anon0 LoopModifies.dfy(136,4): anon17_LoopHead @@ -43,14 +43,14 @@ Execution trace: (0,0): anon21_LoopBody LoopModifies.dfy(141,7): anon22_Else LoopModifies.dfy(141,7): anon24_Else -LoopModifies.dfy(199,10): Error: assignment may update an array element not in the enclosing context's modifies clause +LoopModifies.dfy(199,9): Error: assignment may update an array element not in the enclosing context's modifies clause Execution trace: (0,0): anon0 LoopModifies.dfy(195,4): anon8_LoopHead (0,0): anon8_LoopBody LoopModifies.dfy(195,4): anon9_Else LoopModifies.dfy(195,4): anon11_Else -LoopModifies.dfy(287,13): Error: assignment may update an array element not in the enclosing context's modifies clause +LoopModifies.dfy(287,12): Error: assignment may update an array element not in the enclosing context's modifies clause Execution trace: (0,0): anon0 LoopModifies.dfy(275,4): anon16_LoopHead diff --git a/Test/dafny0/Maps.dfy.expect b/Test/dafny0/Maps.dfy.expect index f46549dd..8b4a6a36 100644 --- a/Test/dafny0/Maps.dfy.expect +++ b/Test/dafny0/Maps.dfy.expect @@ -1,7 +1,7 @@ -Maps.dfy(78,8): Error: element may not be in domain +Maps.dfy(78,7): Error: element may not be in domain Execution trace: (0,0): anon0 -Maps.dfy(128,13): Error: assertion violation +Maps.dfy(128,12): Error: assertion violation Execution trace: (0,0): anon0 diff --git a/Test/dafny0/ModifyStmt.dfy.expect b/Test/dafny0/ModifyStmt.dfy.expect index 4ea872e0..019453d1 100644 --- a/Test/dafny0/ModifyStmt.dfy.expect +++ b/Test/dafny0/ModifyStmt.dfy.expect @@ -1,19 +1,19 @@ -ModifyStmt.dfy(27,14): Error: assertion violation +ModifyStmt.dfy(27,13): Error: assertion violation Execution trace: (0,0): anon0 -ModifyStmt.dfy(42,5): Error: modify statement may violate context's modifies clause +ModifyStmt.dfy(42,4): Error: modify statement may violate context's modifies clause Execution trace: (0,0): anon0 -ModifyStmt.dfy(48,5): Error: modify statement may violate context's modifies clause +ModifyStmt.dfy(48,4): Error: modify statement may violate context's modifies clause Execution trace: (0,0): anon0 -ModifyStmt.dfy(61,5): Error: modify statement may violate context's modifies clause +ModifyStmt.dfy(61,4): Error: modify statement may violate context's modifies clause Execution trace: (0,0): anon0 -ModifyStmt.dfy(70,14): Error: assertion violation +ModifyStmt.dfy(70,13): Error: assertion violation Execution trace: (0,0): anon0 -ModifyStmt.dfy(89,14): Error: assertion violation +ModifyStmt.dfy(89,13): Error: assertion violation Execution trace: (0,0): anon0 (0,0): anon9_Then @@ -22,20 +22,20 @@ Execution trace: ModifyStmt.dfy(81,7): anon11_Else (0,0): anon12_Then (0,0): anon8 -ModifyStmt.dfy(99,14): Error: assertion violation +ModifyStmt.dfy(99,13): Error: assertion violation Execution trace: (0,0): anon0 -ModifyStmt.dfy(110,14): Error: assertion violation +ModifyStmt.dfy(110,13): Error: assertion violation Execution trace: (0,0): anon0 -ModifyStmt.dfy(122,16): Error: assertion violation +ModifyStmt.dfy(122,15): Error: assertion violation Execution trace: (0,0): anon0 (0,0): anon3_Then -ModifyStmt.dfy(134,7): Error: assignment may update an object not in the enclosing context's modifies clause +ModifyStmt.dfy(134,6): Error: assignment may update an object not in the enclosing context's modifies clause Execution trace: (0,0): anon0 -ModifyStmt.dfy(172,15): Error: assertion violation +ModifyStmt.dfy(172,14): Error: assertion violation Execution trace: (0,0): anon0 diff --git a/Test/dafny0/Modules0.dfy.expect b/Test/dafny0/Modules0.dfy.expect index c63ed937..e4b46cce 100644 --- a/Test/dafny0/Modules0.dfy.expect +++ b/Test/dafny0/Modules0.dfy.expect @@ -1,5 +1,5 @@ -Modules0.dfy(333,3): warning: module-level functions are always non-instance, so the 'static' keyword is not allowed here -Modules0.dfy(335,3): warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here +Modules0.dfy(333,2): Warning: module-level functions are always non-instance, so the 'static' keyword is not allowed here +Modules0.dfy(335,2): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here Modules0.dfy(8,8): Error: Duplicate name of top-level declaration: WazzupA Modules0.dfy(9,11): Error: Duplicate name of top-level declaration: WazzupA Modules0.dfy(10,7): Error: Duplicate name of top-level declaration: WazzupA diff --git a/Test/dafny0/Modules1.dfy.expect b/Test/dafny0/Modules1.dfy.expect index 342b5808..feddf46a 100644 --- a/Test/dafny0/Modules1.dfy.expect +++ b/Test/dafny0/Modules1.dfy.expect @@ -1,20 +1,20 @@ -Modules1.dfy(79,16): Error: assertion violation +Modules1.dfy(79,15): Error: assertion violation Execution trace: (0,0): anon0 (0,0): anon3_Then -Modules1.dfy(92,16): Error: assertion violation +Modules1.dfy(92,15): Error: assertion violation Execution trace: (0,0): anon0 (0,0): anon3_Then -Modules1.dfy(94,18): Error: assertion violation +Modules1.dfy(94,17): Error: assertion violation Execution trace: (0,0): anon0 (0,0): anon3_Else -Modules1.dfy(56,9): Error: decreases expression must be bounded below by 0 -Modules1.dfy(54,13): Related location +Modules1.dfy(56,8): Error: decreases expression must be bounded below by 0 +Modules1.dfy(54,12): Related location Execution trace: (0,0): anon0 -Modules1.dfy(62,9): Error: failure to decrease termination measure +Modules1.dfy(62,8): Error: failure to decrease termination measure Execution trace: (0,0): anon0 diff --git a/Test/dafny0/MultiDimArray.dfy.expect b/Test/dafny0/MultiDimArray.dfy.expect index 597ade30..f2bf74de 100644 --- a/Test/dafny0/MultiDimArray.dfy.expect +++ b/Test/dafny0/MultiDimArray.dfy.expect @@ -1,9 +1,9 @@ -MultiDimArray.dfy(56,21): Error: assertion violation +MultiDimArray.dfy(56,20): Error: assertion violation Execution trace: (0,0): anon0 (0,0): anon11_Then (0,0): anon12_Then -MultiDimArray.dfy(83,25): Error: assertion violation +MultiDimArray.dfy(83,24): Error: assertion violation Execution trace: (0,0): anon0 (0,0): anon5_Then diff --git a/Test/dafny0/MultiSets.dfy.expect b/Test/dafny0/MultiSets.dfy.expect index 30534b11..aed70bd2 100644 --- a/Test/dafny0/MultiSets.dfy.expect +++ b/Test/dafny0/MultiSets.dfy.expect @@ -1,24 +1,24 @@ -MultiSets.dfy(159,3): Error BP5003: A postcondition might not hold on this return path. -MultiSets.dfy(158,15): Related location: This is the postcondition that might not hold. +MultiSets.dfy(159,2): Error BP5003: A postcondition might not hold on this return path. +MultiSets.dfy(158,14): Related location: This is the postcondition that might not hold. Execution trace: (0,0): anon0 -MultiSets.dfy(165,3): Error BP5003: A postcondition might not hold on this return path. -MultiSets.dfy(164,15): Related location: This is the postcondition that might not hold. +MultiSets.dfy(165,2): Error BP5003: A postcondition might not hold on this return path. +MultiSets.dfy(164,14): Related location: This is the postcondition that might not hold. Execution trace: (0,0): anon0 -MultiSets.dfy(178,11): Error: new number of occurrences might be negative +MultiSets.dfy(178,10): Error: new number of occurrences might be negative Execution trace: (0,0): anon0 (0,0): anon4_Then (0,0): anon3 -MultiSets.dfy(269,24): Error: assertion violation +MultiSets.dfy(269,23): Error: assertion violation Execution trace: (0,0): anon0 (0,0): anon11_Then (0,0): anon3 (0,0): anon12_Then (0,0): anon14_Else -MultiSets.dfy(292,16): Error: assertion violation +MultiSets.dfy(292,15): Error: assertion violation Execution trace: (0,0): anon0 (0,0): anon8_Then diff --git a/Test/dafny0/NatTypes.dfy.expect b/Test/dafny0/NatTypes.dfy.expect index 5af90253..2bc00e95 100644 --- a/Test/dafny0/NatTypes.dfy.expect +++ b/Test/dafny0/NatTypes.dfy.expect @@ -1,41 +1,41 @@ -NatTypes.dfy(35,12): Error: value assigned to a nat must be non-negative +NatTypes.dfy(35,11): Error: value assigned to a nat must be non-negative Execution trace: (0,0): anon0 NatTypes.dfy(23,5): anon10_LoopHead (0,0): anon10_LoopBody NatTypes.dfy(23,5): anon11_Else (0,0): anon12_Then -NatTypes.dfy(10,5): Error: value assigned to a nat must be non-negative +NatTypes.dfy(10,4): Error: value assigned to a nat must be non-negative Execution trace: (0,0): anon0 -NatTypes.dfy(43,14): Error: assertion violation +NatTypes.dfy(43,13): Error: assertion violation Execution trace: (0,0): anon0 (0,0): anon4_Then -NatTypes.dfy(45,14): Error: assertion violation +NatTypes.dfy(45,13): Error: assertion violation Execution trace: (0,0): anon0 (0,0): anon4_Then -NatTypes.dfy(62,16): Error: assertion violation +NatTypes.dfy(62,15): Error: assertion violation Execution trace: (0,0): anon0 (0,0): anon3_Then -NatTypes.dfy(76,16): Error: assertion violation +NatTypes.dfy(76,15): Error: assertion violation Execution trace: (0,0): anon0 (0,0): anon5_Else (0,0): anon6_Then -NatTypes.dfy(94,22): Error: value assigned to a nat must be non-negative +NatTypes.dfy(94,21): Error: value assigned to a nat must be non-negative Execution trace: (0,0): anon0 (0,0): anon3_Then -NatTypes.dfy(109,45): Error: value assigned to a nat must be non-negative +NatTypes.dfy(109,44): Error: value assigned to a nat must be non-negative Execution trace: (0,0): anon0 (0,0): anon8_Else (0,0): anon9_Else (0,0): anon10_Then -NatTypes.dfy(132,35): Error: value assigned to a nat must be non-negative +NatTypes.dfy(132,34): Error: value assigned to a nat must be non-negative Execution trace: (0,0): anon0 (0,0): anon4_Then diff --git a/Test/dafny0/Newtypes.dfy.expect b/Test/dafny0/Newtypes.dfy.expect index 8e6ff4c5..425ee9a9 100644 --- a/Test/dafny0/Newtypes.dfy.expect +++ b/Test/dafny0/Newtypes.dfy.expect @@ -1,54 +1,54 @@ -Newtypes.dfy(74,11): Error: cannot find witness that shows type is inhabited (sorry, for now, only tried 0) +Newtypes.dfy(74,10): Error: cannot find witness that shows type is inhabited (sorry, for now, only tried 0) Execution trace: (0,0): anon0 -Newtypes.dfy(76,45): Error: possible division by zero +Newtypes.dfy(76,44): Error: possible division by zero Execution trace: (0,0): anon0 (0,0): anon3_Then -Newtypes.dfy(87,14): Error: result of operation might violate newtype constraint +Newtypes.dfy(87,13): Error: result of operation might violate newtype constraint Execution trace: (0,0): anon0 -Newtypes.dfy(95,12): Error: result of operation might violate newtype constraint +Newtypes.dfy(95,11): Error: result of operation might violate newtype constraint Execution trace: (0,0): anon0 (0,0): anon3_Then -Newtypes.dfy(97,14): Error: result of operation might violate newtype constraint +Newtypes.dfy(97,13): Error: result of operation might violate newtype constraint Execution trace: (0,0): anon0 (0,0): anon3_Else -Newtypes.dfy(104,16): Error: result of operation might violate newtype constraint +Newtypes.dfy(104,15): Error: result of operation might violate newtype constraint Execution trace: (0,0): anon0 -Newtypes.dfy(177,14): Error: result of operation might violate newtype constraint +Newtypes.dfy(177,13): Error: result of operation might violate newtype constraint Execution trace: (0,0): anon0 -Newtypes.dfy(193,64): Error: index 0 out of range +Newtypes.dfy(193,63): Error: index 0 out of range Execution trace: (0,0): anon0 (0,0): anon32_Then (0,0): anon33_Then (0,0): anon16 -Newtypes.dfy(194,67): Error: index 1 out of range +Newtypes.dfy(194,66): Error: index 1 out of range Execution trace: (0,0): anon0 (0,0): anon34_Then (0,0): anon35_Then (0,0): anon19 -Newtypes.dfy(222,16): Error: new number of occurrences might be negative +Newtypes.dfy(222,15): Error: new number of occurrences might be negative Execution trace: (0,0): anon0 (0,0): anon6_Then -Newtypes.dfy(225,40): Error: result of operation might violate newtype constraint +Newtypes.dfy(225,39): Error: result of operation might violate newtype constraint Execution trace: (0,0): anon0 (0,0): anon8_Then -Newtypes.dfy(237,19): Error: result of operation might violate newtype constraint +Newtypes.dfy(237,18): Error: result of operation might violate newtype constraint Execution trace: (0,0): anon0 Newtypes.dfy(236,5): anon9_LoopHead (0,0): anon9_LoopBody (0,0): anon10_Then -Newtypes.dfy(277,19): Error: result of operation might violate newtype constraint +Newtypes.dfy(277,18): Error: result of operation might violate newtype constraint Execution trace: (0,0): anon0 Newtypes.dfy(276,5): anon9_LoopHead diff --git a/Test/dafny0/OpaqueFunctions.dfy.expect b/Test/dafny0/OpaqueFunctions.dfy.expect index 2fb1701f..e9f6e60c 100644 --- a/Test/dafny0/OpaqueFunctions.dfy.expect +++ b/Test/dafny0/OpaqueFunctions.dfy.expect @@ -1,86 +1,86 @@ -OpaqueFunctions.dfy(27,16): Error: assertion violation +OpaqueFunctions.dfy(27,15): Error: assertion violation Execution trace: (0,0): anon0 -OpaqueFunctions.dfy(52,8): Error BP5002: A precondition for this call might not hold. -OpaqueFunctions.dfy(24,16): Related location: This is the precondition that might not hold. +OpaqueFunctions.dfy(52,7): Error BP5002: A precondition for this call might not hold. +OpaqueFunctions.dfy(24,15): Related location: This is the precondition that might not hold. Execution trace: (0,0): anon0 -OpaqueFunctions.dfy(58,20): Error: assertion violation +OpaqueFunctions.dfy(58,19): Error: assertion violation Execution trace: (0,0): anon0 -OpaqueFunctions.dfy(60,21): Error: assertion violation +OpaqueFunctions.dfy(60,20): Error: assertion violation Execution trace: (0,0): anon0 (0,0): anon5_Then -OpaqueFunctions.dfy(63,21): Error: assertion violation +OpaqueFunctions.dfy(63,20): Error: assertion violation Execution trace: (0,0): anon0 (0,0): anon6_Then -OpaqueFunctions.dfy(66,21): Error: assertion violation +OpaqueFunctions.dfy(66,20): Error: assertion violation Execution trace: (0,0): anon0 (0,0): anon6_Else -OpaqueFunctions.dfy(77,21): Error: assertion violation +OpaqueFunctions.dfy(77,20): Error: assertion violation Execution trace: (0,0): anon0 (0,0): anon3_Then -OpaqueFunctions.dfy(79,10): Error BP5002: A precondition for this call might not hold. -OpaqueFunctions.dfy[A'](24,16): Related location: This is the precondition that might not hold. +OpaqueFunctions.dfy(79,9): Error BP5002: A precondition for this call might not hold. +OpaqueFunctions.dfy[A'](24,15): Related location: This is the precondition that might not hold. Execution trace: (0,0): anon0 (0,0): anon3_Else -OpaqueFunctions.dfy(86,20): Error: assertion violation +OpaqueFunctions.dfy(86,19): Error: assertion violation Execution trace: (0,0): anon0 -OpaqueFunctions.dfy(88,21): Error: assertion violation +OpaqueFunctions.dfy(88,20): Error: assertion violation Execution trace: (0,0): anon0 (0,0): anon5_Then -OpaqueFunctions.dfy(91,21): Error: assertion violation +OpaqueFunctions.dfy(91,20): Error: assertion violation Execution trace: (0,0): anon0 (0,0): anon6_Then -OpaqueFunctions.dfy(94,21): Error: assertion violation +OpaqueFunctions.dfy(94,20): Error: assertion violation Execution trace: (0,0): anon0 (0,0): anon6_Else -OpaqueFunctions.dfy(105,21): Error: assertion violation +OpaqueFunctions.dfy(105,20): Error: assertion violation Execution trace: (0,0): anon0 (0,0): anon3_Then -OpaqueFunctions.dfy(107,10): Error BP5002: A precondition for this call might not hold. -OpaqueFunctions.dfy[A'](24,16): Related location: This is the precondition that might not hold. +OpaqueFunctions.dfy(107,9): Error BP5002: A precondition for this call might not hold. +OpaqueFunctions.dfy[A'](24,15): Related location: This is the precondition that might not hold. Execution trace: (0,0): anon0 (0,0): anon3_Else -OpaqueFunctions.dfy(114,20): Error: assertion violation +OpaqueFunctions.dfy(114,19): Error: assertion violation Execution trace: (0,0): anon0 -OpaqueFunctions.dfy(116,21): Error: assertion violation +OpaqueFunctions.dfy(116,20): Error: assertion violation Execution trace: (0,0): anon0 (0,0): anon5_Then -OpaqueFunctions.dfy(119,21): Error: assertion violation +OpaqueFunctions.dfy(119,20): Error: assertion violation Execution trace: (0,0): anon0 (0,0): anon6_Then -OpaqueFunctions.dfy(122,21): Error: assertion violation +OpaqueFunctions.dfy(122,20): Error: assertion violation Execution trace: (0,0): anon0 (0,0): anon6_Else -OpaqueFunctions.dfy(138,13): Error: assertion violation +OpaqueFunctions.dfy(138,12): Error: assertion violation Execution trace: (0,0): anon0 -OpaqueFunctions.dfy(202,12): Error: assertion violation +OpaqueFunctions.dfy(202,11): Error: assertion violation Execution trace: (0,0): anon0 -OpaqueFunctions.dfy(218,12): Error: assertion violation +OpaqueFunctions.dfy(218,11): Error: assertion violation Execution trace: (0,0): anon0 -OpaqueFunctions.dfy(170,16): Error: assertion violation +OpaqueFunctions.dfy(170,15): Error: assertion violation Execution trace: (0,0): anon0 -OpaqueFunctions.dfy(185,20): Error: assertion violation +OpaqueFunctions.dfy(185,19): Error: assertion violation Execution trace: (0,0): anon0 diff --git a/Test/dafny0/Parallel.dfy.expect b/Test/dafny0/Parallel.dfy.expect index db551bba..5d9b044f 100644 --- a/Test/dafny0/Parallel.dfy.expect +++ b/Test/dafny0/Parallel.dfy.expect @@ -1,9 +1,9 @@ -Parallel.dfy(297,22): Error: assertion violation +Parallel.dfy(297,21): Error: assertion violation Execution trace: (0,0): anon0 (0,0): anon4_Else -Parallel.dfy(34,10): Error BP5002: A precondition for this call might not hold. -Parallel.dfy(60,14): Related location: This is the precondition that might not hold. +Parallel.dfy(34,9): Error BP5002: A precondition for this call might not hold. +Parallel.dfy(60,13): Related location: This is the precondition that might not hold. Execution trace: (0,0): anon0 (0,0): anon29_Else @@ -12,7 +12,7 @@ Execution trace: (0,0): anon34_Then (0,0): anon35_Then (0,0): anon14 -Parallel.dfy(38,5): Error: target object may be null +Parallel.dfy(38,4): Error: target object may be null Execution trace: (0,0): anon0 (0,0): anon29_Else @@ -22,7 +22,7 @@ Execution trace: (0,0): anon37_Then (0,0): anon38_Then (0,0): anon20 -Parallel.dfy(42,18): Error: possible violation of postcondition of forall statement +Parallel.dfy(42,17): Error: possible violation of postcondition of forall statement Execution trace: (0,0): anon0 (0,0): anon29_Else @@ -32,7 +32,7 @@ Execution trace: (0,0): anon39_Then (0,0): anon40_Then (0,0): anon26 -Parallel.dfy(47,19): Error: assertion violation +Parallel.dfy(47,18): Error: assertion violation Execution trace: (0,0): anon0 (0,0): anon29_Else @@ -41,24 +41,24 @@ Execution trace: (0,0): anon36_Else (0,0): anon39_Then (0,0): anon40_Then -Parallel.dfy(93,19): Error: assertion violation +Parallel.dfy(93,18): Error: assertion violation Execution trace: (0,0): anon0 (0,0): anon10_Else (0,0): anon11_Then -Parallel.dfy(99,20): Error: possible violation of postcondition of forall statement +Parallel.dfy(99,19): Error: possible violation of postcondition of forall statement Execution trace: (0,0): anon0 (0,0): anon10_Else (0,0): anon11_Then (0,0): anon12_Then -Parallel.dfy(122,12): Error: value assigned to a nat must be non-negative +Parallel.dfy(122,11): Error: value assigned to a nat must be non-negative Execution trace: (0,0): anon0 (0,0): anon6_Then (0,0): anon7_Then (0,0): anon3 -Parallel.dfy(185,12): Error: left-hand sides for different forall-statement bound variables may refer to the same location +Parallel.dfy(185,11): Error: left-hand sides for different forall-statement bound variables may refer to the same location Execution trace: (0,0): anon0 (0,0): anon19_Then diff --git a/Test/dafny0/ParseErrors.dfy.expect b/Test/dafny0/ParseErrors.dfy.expect index 30898479..660ed926 100644 --- a/Test/dafny0/ParseErrors.dfy.expect +++ b/Test/dafny0/ParseErrors.dfy.expect @@ -1,17 +1,17 @@ -ParseErrors.dfy(7,19): error: a chain cannot have more than one != operator -ParseErrors.dfy(9,37): error: this operator chain cannot continue with a descending operator -ParseErrors.dfy(10,38): error: this operator chain cannot continue with an ascending operator -ParseErrors.dfy(15,24): error: this operator chain cannot continue with a descending operator -ParseErrors.dfy(18,18): error: this operator cannot be part of a chain -ParseErrors.dfy(19,19): error: this operator cannot be part of a chain -ParseErrors.dfy(20,18): error: this operator cannot be part of a chain -ParseErrors.dfy(21,18): error: chaining not allowed from the previous operator -ParseErrors.dfy(28,19): error: chaining not allowed from the previous operator -ParseErrors.dfy(31,20): error: can only chain disjoint (!!) with itself. -ParseErrors.dfy(58,8): error: the main operator of a calculation must be transitive -ParseErrors.dfy(74,2): error: this operator cannot continue this calculation -ParseErrors.dfy(75,2): error: this operator cannot continue this calculation -ParseErrors.dfy(80,2): error: this operator cannot continue this calculation -ParseErrors.dfy(81,2): error: this operator cannot continue this calculation -ParseErrors.dfy(87,2): error: this operator cannot continue this calculation +ParseErrors.dfy(7,18): Error: a chain cannot have more than one != operator +ParseErrors.dfy(9,36): Error: this operator chain cannot continue with a descending operator +ParseErrors.dfy(10,37): Error: this operator chain cannot continue with an ascending operator +ParseErrors.dfy(15,23): Error: this operator chain cannot continue with a descending operator +ParseErrors.dfy(18,17): Error: this operator cannot be part of a chain +ParseErrors.dfy(19,18): Error: this operator cannot be part of a chain +ParseErrors.dfy(20,17): Error: this operator cannot be part of a chain +ParseErrors.dfy(21,17): Error: chaining not allowed from the previous operator +ParseErrors.dfy(28,18): Error: chaining not allowed from the previous operator +ParseErrors.dfy(31,19): Error: can only chain disjoint (!!) with itself. +ParseErrors.dfy(58,7): Error: the main operator of a calculation must be transitive +ParseErrors.dfy(74,1): Error: this operator cannot continue this calculation +ParseErrors.dfy(75,1): Error: this operator cannot continue this calculation +ParseErrors.dfy(80,1): Error: this operator cannot continue this calculation +ParseErrors.dfy(81,1): Error: this operator cannot continue this calculation +ParseErrors.dfy(87,1): Error: this operator cannot continue this calculation 16 parse errors detected in ParseErrors.dfy diff --git a/Test/dafny0/PredExpr.dfy.expect b/Test/dafny0/PredExpr.dfy.expect index 18d5d73f..80f311cb 100644 --- a/Test/dafny0/PredExpr.dfy.expect +++ b/Test/dafny0/PredExpr.dfy.expect @@ -1,16 +1,16 @@ -PredExpr.dfy(7,12): Error: assertion violation +PredExpr.dfy(7,11): Error: assertion violation Execution trace: (0,0): anon0 (0,0): anon4_Else -PredExpr.dfy(39,15): Error: value assigned to a nat must be non-negative +PredExpr.dfy(39,14): Error: value assigned to a nat must be non-negative Execution trace: (0,0): anon0 (0,0): anon7_Else (0,0): anon8_Else -PredExpr.dfy(52,17): Error: assertion violation +PredExpr.dfy(52,16): Error: assertion violation Execution trace: (0,0): anon0 -PredExpr.dfy(77,14): Error: assertion violation +PredExpr.dfy(77,13): Error: assertion violation Execution trace: (0,0): anon0 (0,0): anon8_Else diff --git a/Test/dafny0/Predicates.dfy.expect b/Test/dafny0/Predicates.dfy.expect index dac4eb3c..2d7ea6f1 100644 --- a/Test/dafny0/Predicates.dfy.expect +++ b/Test/dafny0/Predicates.dfy.expect @@ -1,26 +1,26 @@ -Predicates.dfy[B](21,5): Error BP5003: A postcondition might not hold on this return path. -Predicates.dfy[B](20,15): Related location: This is the postcondition that might not hold. -Predicates.dfy(31,9): Related location +Predicates.dfy[B](21,4): Error BP5003: A postcondition might not hold on this return path. +Predicates.dfy[B](20,14): Related location: This is the postcondition that might not hold. +Predicates.dfy(31,8): Related location Execution trace: (0,0): anon0 -Predicates.dfy(88,16): Error: assertion violation +Predicates.dfy(88,15): Error: assertion violation Execution trace: (0,0): anon0 -Predicates.dfy(92,14): Error: assertion violation +Predicates.dfy(92,13): Error: assertion violation Execution trace: (0,0): anon0 -Predicates.dfy[Tricky_Full](126,5): Error BP5003: A postcondition might not hold on this return path. -Predicates.dfy[Tricky_Full](125,15): Related location: This is the postcondition that might not hold. -Predicates.dfy(136,7): Related location -Predicates.dfy[Tricky_Full](116,9): Related location +Predicates.dfy[Tricky_Full](126,4): Error BP5003: A postcondition might not hold on this return path. +Predicates.dfy[Tricky_Full](125,14): Related location: This is the postcondition that might not hold. +Predicates.dfy(136,6): Related location +Predicates.dfy[Tricky_Full](116,8): Related location Execution trace: (0,0): anon0 -Predicates.dfy(164,5): Error BP5003: A postcondition might not hold on this return path. -Predicates.dfy(163,15): Related location: This is the postcondition that might not hold. +Predicates.dfy(164,4): Error BP5003: A postcondition might not hold on this return path. +Predicates.dfy(163,14): Related location: This is the postcondition that might not hold. Execution trace: (0,0): anon0 -Predicates.dfy[Q1](154,5): Error BP5003: A postcondition might not hold on this return path. -Predicates.dfy[Q1](153,15): Related location: This is the postcondition that might not hold. +Predicates.dfy[Q1](154,4): Error BP5003: A postcondition might not hold on this return path. +Predicates.dfy[Q1](153,14): Related location: This is the postcondition that might not hold. Execution trace: (0,0): anon0 diff --git a/Test/dafny0/Protected.dfy.expect b/Test/dafny0/Protected.dfy.expect index d50f2dd5..6796e847 100644 --- a/Test/dafny0/Protected.dfy.expect +++ b/Test/dafny0/Protected.dfy.expect @@ -1,20 +1,20 @@ -Protected.dfy(17,20): Error: assertion violation +Protected.dfy(17,19): Error: assertion violation Execution trace: (0,0): anon0 (0,0): anon9_Then -Protected.dfy(31,18): Error: assertion violation +Protected.dfy(31,17): Error: assertion violation Execution trace: (0,0): anon0 (0,0): anon12_Then (0,0): anon6 (0,0): anon13_Else -Protected.dfy(35,16): Error: assertion violation +Protected.dfy(35,15): Error: assertion violation Execution trace: (0,0): anon0 -Protected.dfy(48,20): Error: assertion violation +Protected.dfy(48,19): Error: assertion violation Execution trace: (0,0): anon0 -Protected.dfy(55,20): Error: assertion violation +Protected.dfy(55,19): Error: assertion violation Execution trace: (0,0): anon0 diff --git a/Test/dafny0/RankNeg.dfy.expect b/Test/dafny0/RankNeg.dfy.expect index b2686b43..33cd4f1e 100644 --- a/Test/dafny0/RankNeg.dfy.expect +++ b/Test/dafny0/RankNeg.dfy.expect @@ -1,19 +1,19 @@ -RankNeg.dfy(10,26): Error: cannot prove termination; try supplying a decreases clause +RankNeg.dfy(10,25): Error: cannot prove termination; try supplying a decreases clause Execution trace: (0,0): anon0 (0,0): anon7_Else (0,0): anon8_Then -RankNeg.dfy(15,28): Error: cannot prove termination; try supplying a decreases clause +RankNeg.dfy(15,27): Error: cannot prove termination; try supplying a decreases clause Execution trace: (0,0): anon0 (0,0): anon7_Else (0,0): anon8_Then -RankNeg.dfy(22,31): Error: cannot prove termination; try supplying a decreases clause +RankNeg.dfy(22,30): Error: cannot prove termination; try supplying a decreases clause Execution trace: (0,0): anon0 (0,0): anon7_Else (0,0): anon8_Then -RankNeg.dfy(32,25): Error: cannot prove termination; try supplying a decreases clause +RankNeg.dfy(32,24): Error: cannot prove termination; try supplying a decreases clause Execution trace: (0,0): anon0 (0,0): anon7_Else diff --git a/Test/dafny0/Reads.dfy.expect b/Test/dafny0/Reads.dfy.expect index 1199797f..0ef90aec 100644 --- a/Test/dafny0/Reads.dfy.expect +++ b/Test/dafny0/Reads.dfy.expect @@ -1,32 +1,32 @@ -Reads.dfy(133,11): Error: insufficient reads clause to read field +Reads.dfy(133,10): Error: insufficient reads clause to read field Execution trace: (0,0): anon0 -Reads.dfy(9,30): Error: insufficient reads clause to read field +Reads.dfy(9,29): Error: insufficient reads clause to read field Execution trace: (0,0): anon0 -Reads.dfy(18,30): Error: insufficient reads clause to read field +Reads.dfy(18,29): Error: insufficient reads clause to read field Execution trace: (0,0): anon0 -Reads.dfy(28,50): Error: insufficient reads clause to read field +Reads.dfy(28,49): Error: insufficient reads clause to read field Execution trace: (0,0): anon0 -Reads.dfy(37,43): Error: insufficient reads clause to read field +Reads.dfy(37,42): Error: insufficient reads clause to read field Execution trace: (0,0): anon0 (0,0): anon7_Then (0,0): anon4 -Reads.dfy(51,30): Error: insufficient reads clause to read field +Reads.dfy(51,29): Error: insufficient reads clause to read field Execution trace: (0,0): anon0 (0,0): anon10_Then (0,0): anon4 -Reads.dfy(117,36): Error: insufficient reads clause to invoke function +Reads.dfy(117,35): Error: insufficient reads clause to invoke function Execution trace: (0,0): anon0 -Reads.dfy(117,36): Error: possible violation of function precondition +Reads.dfy(117,35): Error: possible violation of function precondition Execution trace: (0,0): anon0 -Reads.dfy(120,38): Error: insufficient reads clause to invoke function +Reads.dfy(120,37): Error: insufficient reads clause to invoke function Execution trace: (0,0): anon0 diff --git a/Test/dafny0/RealCompare.dfy.expect b/Test/dafny0/RealCompare.dfy.expect index 5b25fa25..48524bdf 100644 --- a/Test/dafny0/RealCompare.dfy.expect +++ b/Test/dafny0/RealCompare.dfy.expect @@ -1,19 +1,19 @@ -RealCompare.dfy(35,6): Error: failure to decrease termination measure +RealCompare.dfy(35,5): Error: failure to decrease termination measure Execution trace: (0,0): anon0 (0,0): anon3_Then -RealCompare.dfy(50,4): Error: decreases expression must be bounded below by 0.0 -RealCompare.dfy(48,13): Related location +RealCompare.dfy(50,3): Error: decreases expression must be bounded below by 0.0 +RealCompare.dfy(48,12): Related location Execution trace: (0,0): anon0 -RealCompare.dfy(141,12): Error: assertion violation +RealCompare.dfy(141,11): Error: assertion violation Execution trace: (0,0): anon0 RealCompare.dfy(133,3): anon7_LoopHead (0,0): anon7_LoopBody RealCompare.dfy(133,3): anon8_Else (0,0): anon9_Then -RealCompare.dfy(156,12): Error: assertion violation +RealCompare.dfy(156,11): Error: assertion violation Execution trace: (0,0): anon0 RealCompare.dfy(147,3): anon9_LoopHead diff --git a/Test/dafny0/RealTypes.dfy.expect b/Test/dafny0/RealTypes.dfy.expect index 0d132948..0fce4634 100644 --- a/Test/dafny0/RealTypes.dfy.expect +++ b/Test/dafny0/RealTypes.dfy.expect @@ -1,22 +1,22 @@ -RealTypes.dfy(12,16): Error: the real-based number must be an integer (if you want truncation, apply .Trunc to the real-based number) +RealTypes.dfy(12,15): Error: the real-based number must be an integer (if you want truncation, apply .Trunc to the real-based number) Execution trace: (0,0): anon0 (0,0): anon6_Then -RealTypes.dfy(14,28): Error: assertion violation +RealTypes.dfy(14,27): Error: assertion violation Execution trace: (0,0): anon0 (0,0): anon7_Then -RealTypes.dfy(21,12): Error: possible division by zero +RealTypes.dfy(21,11): Error: possible division by zero Execution trace: (0,0): anon0 RealTypes.dfy(20,23): anon3_Else (0,0): anon2 -RealTypes.dfy(21,20): Error: assertion violation +RealTypes.dfy(21,19): Error: assertion violation Execution trace: (0,0): anon0 RealTypes.dfy(20,23): anon3_Else (0,0): anon2 -RealTypes.dfy(29,12): Error: assertion violation +RealTypes.dfy(29,11): Error: assertion violation Execution trace: (0,0): anon0 diff --git a/Test/dafny0/Refinement.dfy.expect b/Test/dafny0/Refinement.dfy.expect index d03b9412..339c86b4 100644 --- a/Test/dafny0/Refinement.dfy.expect +++ b/Test/dafny0/Refinement.dfy.expect @@ -1,40 +1,40 @@ -Refinement.dfy(15,5): Error BP5003: A postcondition might not hold on this return path. -Refinement.dfy(14,17): Related location: This is the postcondition that might not hold. +Refinement.dfy(15,4): Error BP5003: A postcondition might not hold on this return path. +Refinement.dfy(14,16): Related location: This is the postcondition that might not hold. Execution trace: (0,0): anon0 -Refinement.dfy[B](15,5): Error BP5003: A postcondition might not hold on this return path. -Refinement.dfy(33,20): Related location: This is the postcondition that might not hold. +Refinement.dfy[B](15,4): Error BP5003: A postcondition might not hold on this return path. +Refinement.dfy(33,19): Related location: This is the postcondition that might not hold. Execution trace: (0,0): anon0 -Refinement.dfy(69,16): Error: assertion violation +Refinement.dfy(69,15): Error: assertion violation Execution trace: (0,0): anon0 -Refinement.dfy(80,17): Error: assertion violation +Refinement.dfy(80,16): Error: assertion violation Execution trace: (0,0): anon0 -Refinement.dfy(99,12): Error BP5003: A postcondition might not hold on this return path. -Refinement.dfy(78,15): Related location: This is the postcondition that might not hold. +Refinement.dfy(99,11): Error BP5003: A postcondition might not hold on this return path. +Refinement.dfy(78,14): Related location: This is the postcondition that might not hold. Execution trace: (0,0): anon0 (0,0): anon4_Else -Refinement.dfy(102,3): Error BP5003: A postcondition might not hold on this return path. -Refinement.dfy(83,15): Related location: This is the postcondition that might not hold. +Refinement.dfy(102,2): Error BP5003: A postcondition might not hold on this return path. +Refinement.dfy(83,14): Related location: This is the postcondition that might not hold. Execution trace: (0,0): anon0 -Refinement.dfy(189,5): Error BP5003: A postcondition might not hold on this return path. -Refinement.dfy[IncorrectConcrete](121,15): Related location: This is the postcondition that might not hold. -Refinement.dfy(186,9): Related location +Refinement.dfy(189,4): Error BP5003: A postcondition might not hold on this return path. +Refinement.dfy[IncorrectConcrete](121,14): Related location: This is the postcondition that might not hold. +Refinement.dfy(186,8): Related location Execution trace: (0,0): anon0 -Refinement.dfy(193,5): Error BP5003: A postcondition might not hold on this return path. -Refinement.dfy[IncorrectConcrete](129,15): Related location: This is the postcondition that might not hold. -Refinement.dfy(186,9): Related location +Refinement.dfy(193,4): Error BP5003: A postcondition might not hold on this return path. +Refinement.dfy[IncorrectConcrete](129,14): Related location: This is the postcondition that might not hold. +Refinement.dfy(186,8): Related location Execution trace: (0,0): anon0 (0,0): anon4_Then (0,0): anon3 -Refinement.dfy(199,7): Error: assertion violation -Refinement.dfy[IncorrectConcrete](137,24): Related location +Refinement.dfy(199,6): Error: assertion violation +Refinement.dfy[IncorrectConcrete](137,23): Related location Execution trace: (0,0): anon0 diff --git a/Test/dafny0/Skeletons.dfy.expect b/Test/dafny0/Skeletons.dfy.expect index 43b372c3..4b48bad0 100644 --- a/Test/dafny0/Skeletons.dfy.expect +++ b/Test/dafny0/Skeletons.dfy.expect @@ -1,5 +1,5 @@ -Skeletons.dfy(45,3): Error BP5003: A postcondition might not hold on this return path. -Skeletons.dfy(44,15): Related location: This is the postcondition that might not hold. +Skeletons.dfy(45,2): Error BP5003: A postcondition might not hold on this return path. +Skeletons.dfy(44,14): Related location: This is the postcondition that might not hold. Execution trace: (0,0): anon0 Skeletons.dfy[C0](32,5): anon11_LoopHead diff --git a/Test/dafny0/SmallTests.dfy.expect b/Test/dafny0/SmallTests.dfy.expect index b0605d8e..eee0d4f1 100644 --- a/Test/dafny0/SmallTests.dfy.expect +++ b/Test/dafny0/SmallTests.dfy.expect @@ -1,41 +1,41 @@ -SmallTests.dfy(34,11): Error: index out of range +SmallTests.dfy(34,10): Error: index out of range Execution trace: (0,0): anon0 -SmallTests.dfy(65,36): Error: possible division by zero +SmallTests.dfy(65,35): Error: possible division by zero Execution trace: (0,0): anon0 (0,0): anon13_Then -SmallTests.dfy(66,51): Error: possible division by zero +SmallTests.dfy(66,50): Error: possible division by zero Execution trace: (0,0): anon0 (0,0): anon13_Else (0,0): anon14_Else -SmallTests.dfy(67,22): Error: target object may be null +SmallTests.dfy(67,21): Error: target object may be null Execution trace: (0,0): anon0 (0,0): anon13_Then (0,0): anon14_Then (0,0): anon15_Then -SmallTests.dfy(86,24): Error: target object may be null +SmallTests.dfy(86,23): Error: target object may be null Execution trace: (0,0): anon0 SmallTests.dfy(85,5): anon8_LoopHead (0,0): anon8_LoopBody (0,0): anon9_Then -SmallTests.dfy(120,6): Error: call may violate context's modifies clause +SmallTests.dfy(120,5): Error: call may violate context's modifies clause Execution trace: (0,0): anon0 (0,0): anon4_Else (0,0): anon3 -SmallTests.dfy(133,10): Error: call may violate context's modifies clause +SmallTests.dfy(133,9): Error: call may violate context's modifies clause Execution trace: (0,0): anon0 (0,0): anon3_Then -SmallTests.dfy(135,10): Error: call may violate context's modifies clause +SmallTests.dfy(135,9): Error: call may violate context's modifies clause Execution trace: (0,0): anon0 (0,0): anon3_Else -SmallTests.dfy(175,9): Error: assignment may update an object field not in the enclosing context's modifies clause +SmallTests.dfy(175,8): Error: assignment may update an object field not in the enclosing context's modifies clause Execution trace: (0,0): anon0 (0,0): anon22_Else @@ -44,23 +44,23 @@ Execution trace: (0,0): anon28_Then (0,0): anon29_Then (0,0): anon19 -SmallTests.dfy(199,14): Error: assertion violation +SmallTests.dfy(199,13): Error: assertion violation Execution trace: (0,0): anon0 (0,0): anon9_Then -SmallTests.dfy(206,14): Error: assertion violation +SmallTests.dfy(206,13): Error: assertion violation Execution trace: (0,0): anon0 (0,0): anon9_Else (0,0): anon3 (0,0): anon10_Then -SmallTests.dfy(208,14): Error: assertion violation +SmallTests.dfy(208,13): Error: assertion violation Execution trace: (0,0): anon0 (0,0): anon9_Else (0,0): anon3 (0,0): anon10_Else -SmallTests.dfy(213,14): Error: assertion violation +SmallTests.dfy(213,13): Error: assertion violation Execution trace: (0,0): anon0 (0,0): anon9_Else @@ -68,7 +68,7 @@ Execution trace: (0,0): anon10_Then (0,0): anon6 (0,0): anon11_Then -SmallTests.dfy(215,14): Error: assertion violation +SmallTests.dfy(215,13): Error: assertion violation Execution trace: (0,0): anon0 (0,0): anon9_Else @@ -76,37 +76,37 @@ Execution trace: (0,0): anon10_Then (0,0): anon6 (0,0): anon11_Else -SmallTests.dfy(261,24): Error BP5002: A precondition for this call might not hold. -SmallTests.dfy(239,30): Related location: This is the precondition that might not hold. +SmallTests.dfy(261,23): Error BP5002: A precondition for this call might not hold. +SmallTests.dfy(239,29): Related location: This is the precondition that might not hold. Execution trace: (0,0): anon0 SmallTests.dfy(256,19): anon3_Else (0,0): anon2 -SmallTests.dfy(367,12): Error: assertion violation +SmallTests.dfy(367,11): Error: assertion violation Execution trace: (0,0): anon0 -SmallTests.dfy(377,12): Error: assertion violation +SmallTests.dfy(377,11): Error: assertion violation Execution trace: (0,0): anon0 -SmallTests.dfy(387,6): Error: cannot prove termination; try supplying a decreases clause +SmallTests.dfy(387,5): Error: cannot prove termination; try supplying a decreases clause Execution trace: (0,0): anon0 (0,0): anon4_Else -SmallTests.dfy(692,14): Error: assertion violation +SmallTests.dfy(692,13): Error: assertion violation Execution trace: (0,0): anon0 SmallTests.dfy(689,5): anon7_LoopHead (0,0): anon7_LoopBody SmallTests.dfy(689,5): anon8_Else (0,0): anon9_Then -SmallTests.dfy(713,14): Error: assertion violation +SmallTests.dfy(713,13): Error: assertion violation Execution trace: (0,0): anon0 (0,0): anon7_Then (0,0): anon8_Then (0,0): anon3 -SmallTests.dfy(296,3): Error BP5003: A postcondition might not hold on this return path. -SmallTests.dfy(290,11): Related location: This is the postcondition that might not hold. +SmallTests.dfy(296,2): Error BP5003: A postcondition might not hold on this return path. +SmallTests.dfy(290,10): Related location: This is the postcondition that might not hold. Execution trace: (0,0): anon0 (0,0): anon18_Else @@ -114,29 +114,29 @@ Execution trace: (0,0): anon24_Then (0,0): anon15 (0,0): anon25_Else -SmallTests.dfy(338,12): Error: assertion violation +SmallTests.dfy(338,11): Error: assertion violation Execution trace: (0,0): anon0 (0,0): anon8_Then (0,0): anon7 -SmallTests.dfy(345,10): Error: assertion violation +SmallTests.dfy(345,9): Error: assertion violation Execution trace: (0,0): anon0 -SmallTests.dfy(355,4): Error: cannot prove termination; try supplying a decreases clause +SmallTests.dfy(355,3): Error: cannot prove termination; try supplying a decreases clause Execution trace: (0,0): anon0 (0,0): anon4_Else -SmallTests.dfy(399,10): Error BP5003: A postcondition might not hold on this return path. -SmallTests.dfy(402,41): Related location: This is the postcondition that might not hold. +SmallTests.dfy(399,9): Error BP5003: A postcondition might not hold on this return path. +SmallTests.dfy(402,40): Related location: This is the postcondition that might not hold. Execution trace: (0,0): anon0 (0,0): anon7_Else -SmallTests.dfy(563,12): Error: assertion violation +SmallTests.dfy(563,11): Error: assertion violation Execution trace: (0,0): anon0 (0,0): anon3_Then (0,0): anon2 -SmallTests.dfy(577,20): Error: left-hand sides 0 and 1 may refer to the same location +SmallTests.dfy(577,19): Error: left-hand sides 0 and 1 may refer to the same location Execution trace: (0,0): anon0 (0,0): anon27_Then @@ -148,7 +148,7 @@ Execution trace: (0,0): anon31_Then (0,0): anon32_Then (0,0): anon12 -SmallTests.dfy(579,15): Error: left-hand sides 1 and 2 may refer to the same location +SmallTests.dfy(579,14): Error: left-hand sides 1 and 2 may refer to the same location Execution trace: (0,0): anon0 (0,0): anon27_Then @@ -163,16 +163,16 @@ Execution trace: (0,0): anon37_Then (0,0): anon22 (0,0): anon38_Then -SmallTests.dfy(586,25): Error: target object may be null +SmallTests.dfy(586,24): Error: target object may be null Execution trace: (0,0): anon0 -SmallTests.dfy(599,10): Error: assertion violation +SmallTests.dfy(599,9): Error: assertion violation Execution trace: (0,0): anon0 -SmallTests.dfy(623,5): Error: cannot establish the existence of LHS values that satisfy the such-that predicate +SmallTests.dfy(623,4): Error: cannot establish the existence of LHS values that satisfy the such-that predicate Execution trace: (0,0): anon0 -SmallTests.dfy(646,23): Error: assertion violation +SmallTests.dfy(646,22): Error: assertion violation Execution trace: (0,0): anon0 (0,0): anon8_Then @@ -180,17 +180,17 @@ Execution trace: (0,0): anon4 (0,0): anon10_Then (0,0): anon7 -SmallTests.dfy(660,10): Error: cannot establish the existence of LHS values that satisfy the such-that predicate +SmallTests.dfy(660,9): Error: cannot establish the existence of LHS values that satisfy the such-that predicate Execution trace: (0,0): anon0 (0,0): anon5_Then (0,0): anon6_Then (0,0): anon3 -SmallTests.dfy(662,10): Error: cannot establish the existence of LHS values that satisfy the such-that predicate +SmallTests.dfy(662,9): Error: cannot establish the existence of LHS values that satisfy the such-that predicate Execution trace: (0,0): anon0 (0,0): anon5_Else -SmallTests.dfy(675,9): Error: cannot establish the existence of LHS values that satisfy the such-that predicate +SmallTests.dfy(675,8): Error: cannot establish the existence of LHS values that satisfy the such-that predicate Execution trace: (0,0): anon0 diff --git a/Test/dafny0/SplitExpr.dfy.expect b/Test/dafny0/SplitExpr.dfy.expect index b7ef524f..29dd6eda 100644 --- a/Test/dafny0/SplitExpr.dfy.expect +++ b/Test/dafny0/SplitExpr.dfy.expect @@ -1,5 +1,5 @@ -SplitExpr.dfy(92,15): Error: loop invariant violation -SplitExpr.dfy(86,44): Related location +SplitExpr.dfy(92,14): Error: loop invariant violation +SplitExpr.dfy(86,43): Related location Execution trace: SplitExpr.dfy(91,3): anon7_LoopHead diff --git a/Test/dafny0/StatementExpressions.dfy.expect b/Test/dafny0/StatementExpressions.dfy.expect index 9de6a5d1..936a3954 100644 --- a/Test/dafny0/StatementExpressions.dfy.expect +++ b/Test/dafny0/StatementExpressions.dfy.expect @@ -1,22 +1,22 @@ -StatementExpressions.dfy(55,12): Error: cannot prove termination; try supplying a decreases clause +StatementExpressions.dfy(55,11): Error: cannot prove termination; try supplying a decreases clause Execution trace: (0,0): anon0 (0,0): anon6_Then (0,0): anon8_Then -StatementExpressions.dfy(59,14): Error: assertion violation +StatementExpressions.dfy(59,13): Error: assertion violation Execution trace: (0,0): anon0 (0,0): anon6_Then StatementExpressions.dfy(53,7): anon8_Else -StatementExpressions.dfy(77,6): Error: possible division by zero +StatementExpressions.dfy(77,5): Error: possible division by zero Execution trace: (0,0): anon0 (0,0): anon4_Else -StatementExpressions.dfy(88,5): Error: value assigned to a nat must be non-negative +StatementExpressions.dfy(88,4): Error: value assigned to a nat must be non-negative Execution trace: (0,0): anon0 (0,0): anon4_Else -StatementExpressions.dfy(98,18): Error: cannot prove termination; try supplying a decreases clause +StatementExpressions.dfy(98,17): Error: cannot prove termination; try supplying a decreases clause Execution trace: (0,0): anon0 (0,0): anon6_Then diff --git a/Test/dafny0/Superposition.dfy.expect b/Test/dafny0/Superposition.dfy.expect index 6497c712..04ec2f7d 100644 --- a/Test/dafny0/Superposition.dfy.expect +++ b/Test/dafny0/Superposition.dfy.expect @@ -10,16 +10,16 @@ Verifying CheckWellformed$$_0_M0.C.P ... Verifying CheckWellformed$$_0_M0.C.Q ... [5 proof obligations] error -Superposition.dfy(27,15): Error BP5003: A postcondition might not hold on this return path. -Superposition.dfy(28,26): Related location: This is the postcondition that might not hold. +Superposition.dfy(27,14): Error BP5003: A postcondition might not hold on this return path. +Superposition.dfy(28,25): Related location: This is the postcondition that might not hold. Execution trace: (0,0): anon0 (0,0): anon7_Else Verifying CheckWellformed$$_0_M0.C.R ... [5 proof obligations] error -Superposition.dfy(33,15): Error BP5003: A postcondition might not hold on this return path. -Superposition.dfy(34,26): Related location: This is the postcondition that might not hold. +Superposition.dfy(33,14): Error BP5003: A postcondition might not hold on this return path. +Superposition.dfy(34,25): Related location: This is the postcondition that might not hold. Execution trace: (0,0): anon0 (0,0): anon7_Else @@ -32,8 +32,8 @@ Verifying Impl$$_1_M1.C.M ... Verifying CheckWellformed$$_1_M1.C.P ... [2 proof obligations] error -Superposition.dfy(50,25): Error BP5003: A postcondition might not hold on this return path. -Superposition.dfy[M1](22,26): Related location: This is the postcondition that might not hold. +Superposition.dfy(50,24): Error BP5003: A postcondition might not hold on this return path. +Superposition.dfy[M1](22,25): Related location: This is the postcondition that might not hold. Execution trace: (0,0): anon0 (0,0): anon9_Else diff --git a/Test/dafny0/Termination.dfy.expect b/Test/dafny0/Termination.dfy.expect index 77a9e70e..69cb360d 100644 --- a/Test/dafny0/Termination.dfy.expect +++ b/Test/dafny0/Termination.dfy.expect @@ -1,20 +1,20 @@ -Termination.dfy[TerminationRefinement1](441,6): Error: failure to decrease termination measure +Termination.dfy[TerminationRefinement1](441,5): Error: failure to decrease termination measure Execution trace: (0,0): anon0 -Termination.dfy(361,47): Error: failure to decrease termination measure +Termination.dfy(361,46): Error: failure to decrease termination measure Execution trace: (0,0): anon0 (0,0): anon9_Else (0,0): anon10_Then (0,0): anon11_Else -Termination.dfy(108,3): Error: cannot prove termination; try supplying a decreases clause for the loop +Termination.dfy(108,2): Error: cannot prove termination; try supplying a decreases clause for the loop Execution trace: (0,0): anon0 Termination.dfy(108,3): anon6_LoopHead (0,0): anon6_LoopBody Termination.dfy(108,3): anon7_Else Termination.dfy(108,3): anon8_Else -Termination.dfy(116,3): Error: cannot prove termination; try supplying a decreases clause for the loop +Termination.dfy(116,2): Error: cannot prove termination; try supplying a decreases clause for the loop Execution trace: (0,0): anon0 Termination.dfy(116,3): anon8_LoopHead @@ -23,7 +23,7 @@ Execution trace: (0,0): anon10_Then (0,0): anon5 Termination.dfy(116,3): anon11_Else -Termination.dfy(125,3): Error: decreases expression might not decrease +Termination.dfy(125,2): Error: decreases expression might not decrease Execution trace: (0,0): anon0 Termination.dfy(125,3): anon8_LoopHead @@ -32,7 +32,7 @@ Execution trace: (0,0): anon10_Then (0,0): anon5 Termination.dfy(125,3): anon11_Else -Termination.dfy(126,17): Error: decreases expression must be bounded below by 0 at end of loop iteration +Termination.dfy(126,16): Error: decreases expression must be bounded below by 0 at end of loop iteration Execution trace: (0,0): anon0 Termination.dfy(125,3): anon8_LoopHead @@ -41,13 +41,13 @@ Execution trace: (0,0): anon10_Then (0,0): anon5 Termination.dfy(125,3): anon11_Else -Termination.dfy(255,35): Error: cannot prove termination; try supplying a decreases clause +Termination.dfy(255,34): Error: cannot prove termination; try supplying a decreases clause Execution trace: (0,0): anon0 (0,0): anon8_Else (0,0): anon9_Else (0,0): anon10_Then -Termination.dfy(296,3): Error: decreases expression might not decrease +Termination.dfy(296,2): Error: decreases expression might not decrease Execution trace: Termination.dfy(296,3): anon9_LoopHead (0,0): anon9_LoopBody diff --git a/Test/dafny0/Trait/TraitUsingParentMembers.dfy.expect b/Test/dafny0/Trait/TraitUsingParentMembers.dfy.expect index 9960c1d9..1517dee4 100644 --- a/Test/dafny0/Trait/TraitUsingParentMembers.dfy.expect +++ b/Test/dafny0/Trait/TraitUsingParentMembers.dfy.expect @@ -1,4 +1,4 @@ -TraitUsingParentMembers.dfy(10,8): Error: assignment may update an array element not in the enclosing context's modifies clause +TraitUsingParentMembers.dfy(10,7): Error: assignment may update an array element not in the enclosing context's modifies clause Execution trace: (0,0): anon0 (0,0): anon5_Then diff --git a/Test/dafny0/Trait/TraitsDecreases.dfy.expect b/Test/dafny0/Trait/TraitsDecreases.dfy.expect index 2607a0c6..7d646bd1 100644 --- a/Test/dafny0/Trait/TraitsDecreases.dfy.expect +++ b/Test/dafny0/Trait/TraitsDecreases.dfy.expect @@ -1,34 +1,34 @@ -TraitsDecreases.dfy(117,15): Error: predicate's decreases clause must be below or equal to that in the trait +TraitsDecreases.dfy(117,14): Error: predicate's decreases clause must be below or equal to that in the trait Execution trace: (0,0): anon0 -TraitsDecreases.dfy(124,15): Error: predicate's decreases clause must be below or equal to that in the trait +TraitsDecreases.dfy(124,14): Error: predicate's decreases clause must be below or equal to that in the trait Execution trace: (0,0): anon0 -TraitsDecreases.dfy(131,15): Error: predicate's decreases clause must be below or equal to that in the trait +TraitsDecreases.dfy(131,14): Error: predicate's decreases clause must be below or equal to that in the trait Execution trace: (0,0): anon0 -TraitsDecreases.dfy(138,15): Error: predicate's decreases clause must be below or equal to that in the trait +TraitsDecreases.dfy(138,14): Error: predicate's decreases clause must be below or equal to that in the trait Execution trace: (0,0): anon0 -TraitsDecreases.dfy(145,15): Error: predicate's decreases clause must be below or equal to that in the trait +TraitsDecreases.dfy(145,14): Error: predicate's decreases clause must be below or equal to that in the trait Execution trace: (0,0): anon0 -TraitsDecreases.dfy(152,12): Error: method's decreases clause must be below or equal to that in the trait +TraitsDecreases.dfy(152,11): Error: method's decreases clause must be below or equal to that in the trait Execution trace: (0,0): anon0 -TraitsDecreases.dfy(57,10): Error: method's decreases clause must be below or equal to that in the trait +TraitsDecreases.dfy(57,9): Error: method's decreases clause must be below or equal to that in the trait Execution trace: (0,0): anon0 -TraitsDecreases.dfy(69,10): Error: method's decreases clause must be below or equal to that in the trait +TraitsDecreases.dfy(69,9): Error: method's decreases clause must be below or equal to that in the trait Execution trace: (0,0): anon0 -TraitsDecreases.dfy(72,10): Error: method's decreases clause must be below or equal to that in the trait +TraitsDecreases.dfy(72,9): Error: method's decreases clause must be below or equal to that in the trait Execution trace: (0,0): anon0 -TraitsDecreases.dfy(78,10): Error: method's decreases clause must be below or equal to that in the trait +TraitsDecreases.dfy(78,9): Error: method's decreases clause must be below or equal to that in the trait Execution trace: (0,0): anon0 -TraitsDecreases.dfy(88,10): Error: method's decreases clause must be below or equal to that in the trait +TraitsDecreases.dfy(88,9): Error: method's decreases clause must be below or equal to that in the trait Execution trace: (0,0): anon0 diff --git a/Test/dafny0/Tuples.dfy.expect b/Test/dafny0/Tuples.dfy.expect index 13c706d3..9b5f3a83 100644 --- a/Test/dafny0/Tuples.dfy.expect +++ b/Test/dafny0/Tuples.dfy.expect @@ -1,7 +1,7 @@ -Tuples.dfy(22,19): Error: assertion violation +Tuples.dfy(22,18): Error: assertion violation Execution trace: (0,0): anon0 -Tuples.dfy(24,21): Error: possible division by zero +Tuples.dfy(24,20): Error: possible division by zero Execution trace: (0,0): anon0 diff --git a/Test/dafny0/TypeAntecedents.dfy.expect b/Test/dafny0/TypeAntecedents.dfy.expect index d6eb08e4..2e2f606d 100644 --- a/Test/dafny0/TypeAntecedents.dfy.expect +++ b/Test/dafny0/TypeAntecedents.dfy.expect @@ -1,8 +1,8 @@ -TypeAntecedents.dfy(35,13): Error: assertion violation +TypeAntecedents.dfy(35,12): Error: assertion violation Execution trace: (0,0): anon0 -TypeAntecedents.dfy(58,1): Error BP5003: A postcondition might not hold on this return path. -TypeAntecedents.dfy(57,15): Related location: This is the postcondition that might not hold. +TypeAntecedents.dfy(58,0): Error BP5003: A postcondition might not hold on this return path. +TypeAntecedents.dfy(57,14): Related location: This is the postcondition that might not hold. Execution trace: (0,0): anon0 (0,0): anon25_Then @@ -16,7 +16,7 @@ Execution trace: (0,0): anon34_Then (0,0): anon35_Then (0,0): anon24 -TypeAntecedents.dfy(66,16): Error: assertion violation +TypeAntecedents.dfy(66,15): Error: assertion violation Execution trace: (0,0): anon0 (0,0): anon25_Else diff --git a/Test/dafny0/TypeParameters.dfy.expect b/Test/dafny0/TypeParameters.dfy.expect index 3d00e89a..aca0694d 100644 --- a/Test/dafny0/TypeParameters.dfy.expect +++ b/Test/dafny0/TypeParameters.dfy.expect @@ -1,43 +1,43 @@ -TypeParameters.dfy(47,22): Error: assertion violation +TypeParameters.dfy(47,21): Error: assertion violation Execution trace: (0,0): anon0 -TypeParameters.dfy(69,27): Error: assertion violation +TypeParameters.dfy(69,26): Error: assertion violation Execution trace: (0,0): anon0 (0,0): anon3_Then (0,0): anon2 -TypeParameters.dfy(156,12): Error: assertion violation -TypeParameters.dfy(156,28): Related location +TypeParameters.dfy(156,11): Error: assertion violation +TypeParameters.dfy(156,27): Related location Execution trace: (0,0): anon0 (0,0): anon20_Then TypeParameters.dfy(156,32): anon21_Else (0,0): anon5 -TypeParameters.dfy(158,12): Error: assertion violation -TypeParameters.dfy(158,33): Related location +TypeParameters.dfy(158,11): Error: assertion violation +TypeParameters.dfy(158,32): Related location Execution trace: (0,0): anon0 (0,0): anon23_Then TypeParameters.dfy(158,37): anon24_Else (0,0): anon11 -TypeParameters.dfy(160,12): Error: assertion violation -TypeParameters.dfy(160,20): Related location +TypeParameters.dfy(160,11): Error: assertion violation +TypeParameters.dfy(160,19): Related location Execution trace: (0,0): anon0 (0,0): anon25_Then -TypeParameters.dfy(162,12): Error: assertion violation -TypeParameters.dfy(147,5): Related location -TypeParameters.dfy(162,21): Related location +TypeParameters.dfy(162,11): Error: assertion violation +TypeParameters.dfy(147,4): Related location +TypeParameters.dfy(162,20): Related location Execution trace: (0,0): anon0 (0,0): anon26_Then -TypeParameters.dfy(164,12): Error: assertion violation -TypeParameters.dfy(149,8): Related location +TypeParameters.dfy(164,11): Error: assertion violation +TypeParameters.dfy(149,7): Related location Execution trace: (0,0): anon0 (0,0): anon27_Then -TypeParameters.dfy(178,15): Error BP5005: This loop invariant might not be maintained by the loop. -TypeParameters.dfy(178,38): Related location +TypeParameters.dfy(178,14): Error BP5005: This loop invariant might not be maintained by the loop. +TypeParameters.dfy(178,37): Related location Execution trace: (0,0): anon0 TypeParameters.dfy(171,3): anon16_LoopHead diff --git a/Test/dafny0/columns.dfy b/Test/dafny0/columns.dfy new file mode 100644 index 00000000..e36142be --- /dev/null +++ b/Test/dafny0/columns.dfy @@ -0,0 +1,10 @@ +// RUN: %dafny "%s" > "%t" +// RUN: %diff "%s.expect" "%t" + +// Dafny counts columns from 0, but Boogie from one, so for a while there were small bugs with that. + +static method A(x:int) requires x > 0 { // error os 's' + assert (forall y :: y > x ==> y > 100); // error on '(' + assert x != 1; // error on '!' + assert x in {}; // error on 'i' +} diff --git a/Test/dafny0/columns.dfy.expect b/Test/dafny0/columns.dfy.expect new file mode 100644 index 00000000..295ca351 --- /dev/null +++ b/Test/dafny0/columns.dfy.expect @@ -0,0 +1,18 @@ +columns.dfy(6,0): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here +columns.dfy(7,9): Error: assertion violation +Execution trace: + (0,0): anon0 + (0,0): anon3_Then + (0,0): anon2 +columns.dfy(8,11): Error: assertion violation +Execution trace: + (0,0): anon0 + (0,0): anon3_Then + (0,0): anon2 +columns.dfy(9,11): Error: assertion violation +Execution trace: + (0,0): anon0 + (0,0): anon3_Then + (0,0): anon2 + +Dafny program verifier finished with 1 verified, 3 errors diff --git a/Test/dafny0/snapshots/Snapshots0.run.dfy.expect b/Test/dafny0/snapshots/Snapshots0.run.dfy.expect index 96c280d9..d32cd9bb 100644 --- a/Test/dafny0/snapshots/Snapshots0.run.dfy.expect +++ b/Test/dafny0/snapshots/Snapshots0.run.dfy.expect @@ -18,7 +18,7 @@ Processing command (at ) a##cached##0 := a##cached##0 && ##ext >>> AssumeNegationOfAssumptionVariable Processing command (at Snapshots0.v1.dfy(4,10)) assert Lit(false); >>> MarkAsPartiallyVerified -Snapshots0.v1.dfy(4,10): Error: assertion violation +Snapshots0.v1.dfy(4,9): Error: assertion violation Execution trace: (0,0): anon0 diff --git a/Test/dafny0/snapshots/Snapshots1.run.dfy.expect b/Test/dafny0/snapshots/Snapshots1.run.dfy.expect index 878f9905..6d5e43f8 100644 --- a/Test/dafny0/snapshots/Snapshots1.run.dfy.expect +++ b/Test/dafny0/snapshots/Snapshots1.run.dfy.expect @@ -14,7 +14,7 @@ Processing command (at Snapshots1.v1.dfy(3,4)) assert (forall $o: ref, $f >>> MarkAsFullyVerified Processing command (at Snapshots1.v1.dfy(4,10)) assert Lit(false); >>> DoNothingToAssert -Snapshots1.v1.dfy(4,10): Error: assertion violation +Snapshots1.v1.dfy(4,9): Error: assertion violation Execution trace: (0,0): anon0 diff --git a/Test/dafny0/snapshots/Snapshots2.run.dfy.expect b/Test/dafny0/snapshots/Snapshots2.run.dfy.expect index a6a9bc4c..ee2ceecd 100644 --- a/Test/dafny0/snapshots/Snapshots2.run.dfy.expect +++ b/Test/dafny0/snapshots/Snapshots2.run.dfy.expect @@ -26,7 +26,7 @@ Processing command (at Snapshots2.v1.dfy(3,4)) assert (forall $o: ref, $f >>> MarkAsFullyVerified Processing command (at Snapshots2.v1.dfy(4,10)) assert Lit(false); >>> DoNothingToAssert -Snapshots2.v1.dfy(4,10): Error: assertion violation +Snapshots2.v1.dfy(4,9): Error: assertion violation Execution trace: (0,0): anon0 Processing command (at Snapshots2.v1.dfy(11,11)) assert true; diff --git a/Test/dafny0/snapshots/Snapshots3.run.dfy.expect b/Test/dafny0/snapshots/Snapshots3.run.dfy.expect index 07e2d063..accacd90 100644 --- a/Test/dafny0/snapshots/Snapshots3.run.dfy.expect +++ b/Test/dafny0/snapshots/Snapshots3.run.dfy.expect @@ -1,6 +1,6 @@ Processing command (at Snapshots3.v0.dfy(9,14)) assert Lit(0 != 0); >>> DoNothingToAssert -Snapshots3.v0.dfy(9,14): Error: assertion violation +Snapshots3.v0.dfy(9,13): Error: assertion violation Execution trace: (0,0): anon0 (0,0): anon3_Else @@ -10,7 +10,7 @@ Processing command (at Snapshots3.v1.dfy(5,12)) assert Lit(true); >>> DoNothingToAssert Processing command (at Snapshots3.v1.dfy(9,14)) assert Lit(0 != 0); >>> RecycleError -Snapshots3.v0.dfy(9,14): Error: assertion violation +Snapshots3.v0.dfy(9,13): Error: assertion violation Execution trace: (0,0): anon0 (0,0): anon3_Else diff --git a/Test/dafny0/snapshots/Snapshots4.run.dfy.expect b/Test/dafny0/snapshots/Snapshots4.run.dfy.expect index fdc97775..d56eb9d0 100644 --- a/Test/dafny0/snapshots/Snapshots4.run.dfy.expect +++ b/Test/dafny0/snapshots/Snapshots4.run.dfy.expect @@ -8,11 +8,11 @@ Processing command (at Snapshots4.v1.dfy(9,14)) assert LitInt(0) == LitInt(0); >>> MarkAsFullyVerified Processing command (at Snapshots4.v1.dfy(10,14)) assert Lit(2 != 2); >>> DoNothingToAssert -Snapshots4.v1.dfy(5,14): Error: assertion violation +Snapshots4.v1.dfy(5,13): Error: assertion violation Execution trace: (0,0): anon0 (0,0): anon3_Then -Snapshots4.v1.dfy(10,14): Error: assertion violation +Snapshots4.v1.dfy(10,13): Error: assertion violation Execution trace: (0,0): anon0 (0,0): anon3_Else diff --git a/Test/dafny0/snapshots/Snapshots6.run.dfy.expect b/Test/dafny0/snapshots/Snapshots6.run.dfy.expect index af440327..bef5a87d 100644 --- a/Test/dafny0/snapshots/Snapshots6.run.dfy.expect +++ b/Test/dafny0/snapshots/Snapshots6.run.dfy.expect @@ -4,7 +4,7 @@ Processing command (at Snapshots6.v0.dfy(20,14)) assert Lit(false); Dafny program verifier finished with 4 verified, 0 errors Processing command (at Snapshots6.v1.dfy(20,14)) assert Lit(false); >>> DoNothingToAssert -Snapshots6.v1.dfy(20,14): Error: assertion violation +Snapshots6.v1.dfy(20,13): Error: assertion violation Execution trace: (0,0): anon0 diff --git a/Test/dafny0/snapshots/Snapshots7.run.dfy.expect b/Test/dafny0/snapshots/Snapshots7.run.dfy.expect index 7c073a9a..b90a6034 100644 --- a/Test/dafny0/snapshots/Snapshots7.run.dfy.expect +++ b/Test/dafny0/snapshots/Snapshots7.run.dfy.expect @@ -24,7 +24,7 @@ Processing command (at ) a##cached##0 := a##cached##0 && ##ext >>> AssumeNegationOfAssumptionVariable Processing command (at Snapshots7.v1.dfy(19,14)) assert Lit(false); >>> MarkAsPartiallyVerified -Snapshots7.v1.dfy(19,14): Error: assertion violation +Snapshots7.v1.dfy(19,13): Error: assertion violation Execution trace: (0,0): anon0 diff --git a/Test/dafny1/MoreInduction.dfy.expect b/Test/dafny1/MoreInduction.dfy.expect index c8785e56..5de0ace6 100644 --- a/Test/dafny1/MoreInduction.dfy.expect +++ b/Test/dafny1/MoreInduction.dfy.expect @@ -1,17 +1,17 @@ -MoreInduction.dfy(78,1): Error BP5003: A postcondition might not hold on this return path. -MoreInduction.dfy(77,11): Related location: This is the postcondition that might not hold. +MoreInduction.dfy(78,0): Error BP5003: A postcondition might not hold on this return path. +MoreInduction.dfy(77,10): Related location: This is the postcondition that might not hold. Execution trace: (0,0): anon0 -MoreInduction.dfy(83,1): Error BP5003: A postcondition might not hold on this return path. -MoreInduction.dfy(82,21): Related location: This is the postcondition that might not hold. +MoreInduction.dfy(83,0): Error BP5003: A postcondition might not hold on this return path. +MoreInduction.dfy(82,20): Related location: This is the postcondition that might not hold. Execution trace: (0,0): anon0 -MoreInduction.dfy(88,1): Error BP5003: A postcondition might not hold on this return path. -MoreInduction.dfy(87,11): Related location: This is the postcondition that might not hold. +MoreInduction.dfy(88,0): Error BP5003: A postcondition might not hold on this return path. +MoreInduction.dfy(87,10): Related location: This is the postcondition that might not hold. Execution trace: (0,0): anon0 -MoreInduction.dfy(93,1): Error BP5003: A postcondition might not hold on this return path. -MoreInduction.dfy(92,22): Related location: This is the postcondition that might not hold. +MoreInduction.dfy(93,0): Error BP5003: A postcondition might not hold on this return path. +MoreInduction.dfy(92,21): Related location: This is the postcondition that might not hold. Execution trace: (0,0): anon0 diff --git a/Test/dafny2/SnapshotableTrees.dfy.expect b/Test/dafny2/SnapshotableTrees.dfy.expect index 849b9e38..808fe0f9 100644 --- a/Test/dafny2/SnapshotableTrees.dfy.expect +++ b/Test/dafny2/SnapshotableTrees.dfy.expect @@ -1,5 +1,5 @@ -SnapshotableTrees.dfy(68,24): Error BP5002: A precondition for this call might not hold. -SnapshotableTrees.dfy(648,16): Related location: This is the precondition that might not hold. +SnapshotableTrees.dfy(68,23): Error BP5002: A precondition for this call might not hold. +SnapshotableTrees.dfy(648,15): Related location: This is the precondition that might not hold. Execution trace: (0,0): anon0 (0,0): anon3_Then diff --git a/Test/dafny4/BinarySearch.dfy.expect b/Test/dafny4/BinarySearch.dfy.expect index 944f677a..a9f834b7 100644 --- a/Test/dafny4/BinarySearch.dfy.expect +++ b/Test/dafny4/BinarySearch.dfy.expect @@ -1,4 +1,4 @@ -BinarySearch.dfy(44,20): Error: result of operation might violate newtype constraint +BinarySearch.dfy(44,19): Error: result of operation might violate newtype constraint Execution trace: (0,0): anon0 BinarySearch.dfy(40,3): anon18_LoopHead diff --git a/Test/dafny4/Bug73.dfy.expect b/Test/dafny4/Bug73.dfy.expect index 6cf5c156..8beaa18c 100644 --- a/Test/dafny4/Bug73.dfy.expect +++ b/Test/dafny4/Bug73.dfy.expect @@ -1,9 +1,9 @@ -Bug73.dfy(7,14): Error: assertion violation +Bug73.dfy(7,13): Error: assertion violation Execution trace: (0,0): anon0 Bug73.dfy(7,19): anon3_Else (0,0): anon2 -Bug73.dfy(13,14): Error: assertion violation +Bug73.dfy(13,13): Error: assertion violation Execution trace: (0,0): anon0 Bug73.dfy(13,20): anon3_Else diff --git a/Test/dafny4/SoftwareFoundations-Basics.dfy.expect b/Test/dafny4/SoftwareFoundations-Basics.dfy.expect index 0f9eb8d0..f07b068f 100644 --- a/Test/dafny4/SoftwareFoundations-Basics.dfy.expect +++ b/Test/dafny4/SoftwareFoundations-Basics.dfy.expect @@ -1,4 +1,4 @@ -SoftwareFoundations-Basics.dfy(41,12): Error: assertion violation +SoftwareFoundations-Basics.dfy(41,11): Error: assertion violation Execution trace: (0,0): anon0 diff --git a/Test/hofs/Apply.dfy.expect b/Test/hofs/Apply.dfy.expect index 77d34c4c..0a923143 100644 --- a/Test/hofs/Apply.dfy.expect +++ b/Test/hofs/Apply.dfy.expect @@ -1,4 +1,4 @@ -Apply.dfy(27,16): Error: assertion violation +Apply.dfy(27,15): Error: assertion violation Execution trace: (0,0): anon0 Apply.dfy(26,27): anon15_Else diff --git a/Test/hofs/Classes.dfy.expect b/Test/hofs/Classes.dfy.expect index 1c9e31f0..a5b33522 100644 --- a/Test/hofs/Classes.dfy.expect +++ b/Test/hofs/Classes.dfy.expect @@ -1,7 +1,7 @@ -Classes.dfy(64,12): Error: assertion violation +Classes.dfy(64,11): Error: assertion violation Execution trace: (0,0): anon0 -Classes.dfy(40,6): Error: possible violation of function precondition +Classes.dfy(40,5): Error: possible violation of function precondition Execution trace: (0,0): anon0 (0,0): anon7_Else diff --git a/Test/hofs/Field.dfy.expect b/Test/hofs/Field.dfy.expect index 9f6998f5..0859d83c 100644 --- a/Test/hofs/Field.dfy.expect +++ b/Test/hofs/Field.dfy.expect @@ -1,13 +1,13 @@ -Field.dfy(12,12): Error: possible violation of function precondition +Field.dfy(12,11): Error: possible violation of function precondition Execution trace: (0,0): anon0 -Field.dfy(12,15): Error: assertion violation +Field.dfy(12,14): Error: assertion violation Execution trace: (0,0): anon0 -Field.dfy(21,12): Error: possible violation of function precondition +Field.dfy(21,11): Error: possible violation of function precondition Execution trace: (0,0): anon0 -Field.dfy(21,14): Error: assertion violation +Field.dfy(21,13): Error: assertion violation Execution trace: (0,0): anon0 diff --git a/Test/hofs/FnRef.dfy.expect b/Test/hofs/FnRef.dfy.expect index 0f6f2aa9..e665c830 100644 --- a/Test/hofs/FnRef.dfy.expect +++ b/Test/hofs/FnRef.dfy.expect @@ -1,19 +1,19 @@ -FnRef.dfy(17,45): Error: possible violation of function precondition +FnRef.dfy(17,44): Error: possible violation of function precondition Execution trace: (0,0): anon0 FnRef.dfy(15,12): anon5_Else (0,0): anon6_Then -FnRef.dfy(32,8): Error: possible violation of function precondition +FnRef.dfy(32,7): Error: possible violation of function precondition Execution trace: (0,0): anon0 FnRef.dfy(26,12): anon9_Else FnRef.dfy(28,8): anon10_Else -FnRef.dfy(46,12): Error: assertion violation +FnRef.dfy(46,11): Error: assertion violation Execution trace: (0,0): anon0 FnRef.dfy(43,12): anon7_Else (0,0): anon9_Then -FnRef.dfy(65,14): Error: assertion violation +FnRef.dfy(65,13): Error: assertion violation Execution trace: (0,0): anon0 FnRef.dfy(56,12): anon8_Else diff --git a/Test/hofs/Frame.dfy.expect b/Test/hofs/Frame.dfy.expect index 0ee2eadb..9964deb4 100644 --- a/Test/hofs/Frame.dfy.expect +++ b/Test/hofs/Frame.dfy.expect @@ -1,35 +1,35 @@ -Frame.dfy(23,16): Error: assertion violation +Frame.dfy(23,15): Error: assertion violation Execution trace: (0,0): anon0 Frame.dfy(19,12): anon5_Else (0,0): anon6_Then -Frame.dfy(37,14): Error: assertion violation +Frame.dfy(37,13): Error: assertion violation Execution trace: (0,0): anon0 Frame.dfy(33,12): anon3_Else -Frame.dfy(63,23): Error: assertion violation +Frame.dfy(63,22): Error: assertion violation Execution trace: (0,0): anon0 (0,0): anon13_Then Frame.dfy(55,12): anon14_Else (0,0): anon15_Then (0,0): anon5 -Frame.dfy(66,19): Error: insufficient reads clause to read array element +Frame.dfy(66,18): Error: insufficient reads clause to read array element Execution trace: (0,0): anon0 (0,0): anon16_Then (0,0): anon17_Then -Frame.dfy(68,28): Error: insufficient reads clause to read array element +Frame.dfy(68,27): Error: insufficient reads clause to read array element Execution trace: (0,0): anon0 (0,0): anon16_Else (0,0): anon18_Then -Frame.dfy(123,14): Error: possible violation of function precondition +Frame.dfy(123,13): Error: possible violation of function precondition Execution trace: (0,0): anon0 (0,0): anon5_Then (0,0): anon6_Else -Frame.dfy(123,19): Error: assertion violation +Frame.dfy(123,18): Error: assertion violation Execution trace: (0,0): anon0 (0,0): anon5_Then diff --git a/Test/hofs/Lambda.dfy.expect b/Test/hofs/Lambda.dfy.expect index 4fe8275f..ab57fbe0 100644 --- a/Test/hofs/Lambda.dfy.expect +++ b/Test/hofs/Lambda.dfy.expect @@ -1,4 +1,4 @@ -Lambda.dfy(24,12): Error: assertion violation +Lambda.dfy(24,11): Error: assertion violation Execution trace: (0,0): anon0 Lambda.dfy(6,24): anon31_Else diff --git a/Test/hofs/LambdaParsefail.dfy.expect b/Test/hofs/LambdaParsefail.dfy.expect index 11deb9b0..a72fc978 100644 --- a/Test/hofs/LambdaParsefail.dfy.expect +++ b/Test/hofs/LambdaParsefail.dfy.expect @@ -1,6 +1,6 @@ -LambdaParsefail.dfy(5,19): error: this symbol not expected in VarDeclStatement -LambdaParsefail.dfy(6,19): error: this symbol not expected in VarDeclStatement -LambdaParsefail.dfy(7,21): error: this symbol not expected in VarDeclStatement -LambdaParsefail.dfy(8,15): error: cannot declare identifier beginning with underscore -LambdaParsefail.dfy(9,17): error: this symbol not expected in VarDeclStatement +LambdaParsefail.dfy(5,18): Error: this symbol not expected in VarDeclStatement +LambdaParsefail.dfy(6,18): Error: this symbol not expected in VarDeclStatement +LambdaParsefail.dfy(7,20): Error: this symbol not expected in VarDeclStatement +LambdaParsefail.dfy(8,14): Error: cannot declare identifier beginning with underscore +LambdaParsefail.dfy(9,16): Error: this symbol not expected in VarDeclStatement 5 parse errors detected in LambdaParsefail.dfy diff --git a/Test/hofs/LambdaParsefail2.dfy.expect b/Test/hofs/LambdaParsefail2.dfy.expect index 0c9ecb83..1a6a65dc 100644 --- a/Test/hofs/LambdaParsefail2.dfy.expect +++ b/Test/hofs/LambdaParsefail2.dfy.expect @@ -1,2 +1,2 @@ -LambdaParsefail2.dfy(6,39): error: invalid LambdaArrow +LambdaParsefail2.dfy(6,38): Error: invalid LambdaArrow 1 parse errors detected in LambdaParsefail2.dfy diff --git a/Test/hofs/Naked.dfy.expect b/Test/hofs/Naked.dfy.expect index 514952a1..9794478d 100644 --- a/Test/hofs/Naked.dfy.expect +++ b/Test/hofs/Naked.dfy.expect @@ -1,45 +1,45 @@ -Naked.dfy(9,16): Error: cannot use naked function in recursive setting. Possible solution: eta expansion. +Naked.dfy(9,15): Error: cannot use naked function in recursive setting. Possible solution: eta expansion. Execution trace: (0,0): anon0 (0,0): anon9_Else (0,0): anon10_Else (0,0): anon11_Then -Naked.dfy(12,8): Error: cannot use naked function in recursive setting. Possible solution: eta expansion. +Naked.dfy(12,7): Error: cannot use naked function in recursive setting. Possible solution: eta expansion. Execution trace: (0,0): anon0 (0,0): anon9_Else (0,0): anon10_Else (0,0): anon11_Else -Naked.dfy(17,53): Error: cannot use naked function in recursive setting. Possible solution: eta expansion. +Naked.dfy(17,52): Error: cannot use naked function in recursive setting. Possible solution: eta expansion. Execution trace: (0,0): anon0 (0,0): anon7_Else (0,0): anon8_Else -Naked.dfy(22,13): Error: cannot use naked function in recursive setting. Possible solution: eta expansion. +Naked.dfy(22,12): Error: cannot use naked function in recursive setting. Possible solution: eta expansion. Execution trace: (0,0): anon0 -Naked.dfy(26,14): Error: cannot use naked function in recursive setting. Possible solution: eta expansion. +Naked.dfy(26,13): Error: cannot use naked function in recursive setting. Possible solution: eta expansion. Execution trace: (0,0): anon0 -Naked.dfy(30,45): Error: possible violation of function precondition -Naked.dfy(32,14): Related location +Naked.dfy(30,44): Error: possible violation of function precondition +Naked.dfy(32,13): Related location Execution trace: (0,0): anon0 (0,0): anon4_Else -Naked.dfy(32,15): Error: cannot use naked function in recursive setting. Possible solution: eta expansion. +Naked.dfy(32,14): Error: cannot use naked function in recursive setting. Possible solution: eta expansion. Execution trace: (0,0): anon0 -Naked.dfy(38,9): Error: cannot use naked function in recursive setting. Possible solution: eta expansion. +Naked.dfy(38,8): Error: cannot use naked function in recursive setting. Possible solution: eta expansion. Execution trace: (0,0): anon0 -Naked.dfy(42,10): Error: cannot use naked function in recursive setting. Possible solution: eta expansion. +Naked.dfy(42,9): Error: cannot use naked function in recursive setting. Possible solution: eta expansion. Execution trace: (0,0): anon0 -Naked.dfy(45,30): Error: cannot prove termination; try supplying a decreases clause +Naked.dfy(45,29): Error: cannot prove termination; try supplying a decreases clause Execution trace: (0,0): anon0 (0,0): anon4_Else -Naked.dfy(48,11): Error: cannot use naked function in recursive setting. Possible solution: eta expansion. +Naked.dfy(48,10): Error: cannot use naked function in recursive setting. Possible solution: eta expansion. Execution trace: (0,0): anon0 diff --git a/Test/hofs/OneShot.dfy.expect b/Test/hofs/OneShot.dfy.expect index 91b931b8..0b4a2bb8 100644 --- a/Test/hofs/OneShot.dfy.expect +++ b/Test/hofs/OneShot.dfy.expect @@ -1,16 +1,16 @@ -OneShot.dfy(20,12): Error: possible violation of function precondition +OneShot.dfy(20,11): Error: possible violation of function precondition Execution trace: (0,0): anon0 (0,0): anon5_Then OneShot.dfy(13,8): anon5_Else (0,0): anon6_Then -OneShot.dfy(22,12): Error: assertion violation +OneShot.dfy(22,11): Error: assertion violation Execution trace: (0,0): anon0 (0,0): anon5_Then OneShot.dfy(13,8): anon5_Else (0,0): anon6_Else -OneShot.dfy(22,13): Error: possible violation of function precondition +OneShot.dfy(22,12): Error: possible violation of function precondition Execution trace: (0,0): anon0 (0,0): anon5_Then diff --git a/Test/hofs/ReadsReads.dfy.expect b/Test/hofs/ReadsReads.dfy.expect index cd013630..0a374c44 100644 --- a/Test/hofs/ReadsReads.dfy.expect +++ b/Test/hofs/ReadsReads.dfy.expect @@ -1,33 +1,33 @@ -ReadsReads.dfy(31,7): Error: insufficient reads clause to invoke function +ReadsReads.dfy(31,6): Error: insufficient reads clause to invoke function Execution trace: (0,0): anon0 (0,0): anon4_Else -ReadsReads.dfy(36,5): Error: insufficient reads clause to invoke function +ReadsReads.dfy(36,4): Error: insufficient reads clause to invoke function Execution trace: (0,0): anon0 (0,0): anon4_Else -ReadsReads.dfy(47,12): Error: insufficient reads clause to invoke function +ReadsReads.dfy(47,11): Error: insufficient reads clause to invoke function Execution trace: (0,0): anon0 (0,0): anon4_Else -ReadsReads.dfy(58,7): Error: insufficient reads clause to invoke function +ReadsReads.dfy(58,6): Error: insufficient reads clause to invoke function Execution trace: (0,0): anon0 (0,0): anon4_Else -ReadsReads.dfy(87,50): Error: assertion violation +ReadsReads.dfy(87,49): Error: assertion violation Execution trace: (0,0): anon0 (0,0): anon16_Then -ReadsReads.dfy(89,29): Error: assertion violation +ReadsReads.dfy(89,28): Error: assertion violation Execution trace: (0,0): anon0 (0,0): anon18_Then -ReadsReads.dfy(99,37): Error: assertion violation +ReadsReads.dfy(99,36): Error: assertion violation Execution trace: (0,0): anon0 ReadsReads.dfy(96,14): anon15_Else (0,0): anon19_Then -ReadsReads.dfy(101,29): Error: assertion violation +ReadsReads.dfy(101,28): Error: assertion violation Execution trace: (0,0): anon0 ReadsReads.dfy(96,14): anon15_Else diff --git a/Test/hofs/Simple.dfy.expect b/Test/hofs/Simple.dfy.expect index e2f16ef3..c0123c80 100644 --- a/Test/hofs/Simple.dfy.expect +++ b/Test/hofs/Simple.dfy.expect @@ -1,26 +1,26 @@ -Simple.dfy(14,10): Error: possible division by zero +Simple.dfy(14,9): Error: possible division by zero Execution trace: (0,0): anon0 (0,0): anon6_Else (0,0): anon7_Then -Simple.dfy(27,10): Error: possible division by zero +Simple.dfy(27,9): Error: possible division by zero Execution trace: (0,0): anon0 (0,0): anon6_Else (0,0): anon7_Then -Simple.dfy(37,9): Error: possible violation of function precondition +Simple.dfy(37,8): Error: possible violation of function precondition Execution trace: (0,0): anon0 Simple.dfy(35,13): anon5_Else -Simple.dfy(49,9): Error: possible violation of function precondition +Simple.dfy(49,8): Error: possible violation of function precondition Execution trace: (0,0): anon0 (0,0): anon3_Then (0,0): anon2 -Simple.dfy(61,10): Error: possible violation of function precondition +Simple.dfy(61,9): Error: possible violation of function precondition Execution trace: (0,0): anon0 -Simple.dfy(73,10): Error: assertion violation +Simple.dfy(73,9): Error: assertion violation Execution trace: (0,0): anon0 Simple.dfy(72,38): anon5_Else diff --git a/Test/hofs/Twice.dfy.expect b/Test/hofs/Twice.dfy.expect index 2476b945..0ce2450c 100644 --- a/Test/hofs/Twice.dfy.expect +++ b/Test/hofs/Twice.dfy.expect @@ -1,8 +1,8 @@ -Twice.dfy(27,22): Error: assertion violation +Twice.dfy(27,21): Error: assertion violation Execution trace: (0,0): anon0 Twice.dfy(23,12): anon3_Else -Twice.dfy(35,32): Error: possible violation of function precondition +Twice.dfy(35,31): Error: possible violation of function precondition Execution trace: (0,0): anon0 (0,0): anon10_Else diff --git a/Test/irondafny0/inheritreqs0.dfy.expect b/Test/irondafny0/inheritreqs0.dfy.expect index eaadc85a..44e33bc0 100644 --- a/Test/irondafny0/inheritreqs0.dfy.expect +++ b/Test/irondafny0/inheritreqs0.dfy.expect @@ -1,5 +1,5 @@ -inheritreqs0.dfy(19,14): Error BP5002: A precondition for this call might not hold. -inheritreqs0.dfy[Impl](6,18): Related location: This is the precondition that might not hold. +inheritreqs0.dfy(19,13): Error BP5002: A precondition for this call might not hold. +inheritreqs0.dfy[Impl](6,17): Related location: This is the precondition that might not hold. Execution trace: (0,0): anon0 diff --git a/Test/irondafny0/inheritreqs1.dfy.expect b/Test/irondafny0/inheritreqs1.dfy.expect index 27c76fee..a07d179d 100644 --- a/Test/irondafny0/inheritreqs1.dfy.expect +++ b/Test/irondafny0/inheritreqs1.dfy.expect @@ -1,5 +1,5 @@ -inheritreqs1.dfy(20,14): Error BP5002: A precondition for this call might not hold. -inheritreqs1.dfy(15,18): Related location: This is the precondition that might not hold. +inheritreqs1.dfy(20,13): Error BP5002: A precondition for this call might not hold. +inheritreqs1.dfy(15,17): Related location: This is the precondition that might not hold. Execution trace: (0,0): anon0 diff --git a/Test/irondafny0/xrefine1.dfy.expect b/Test/irondafny0/xrefine1.dfy.expect index ae844fc8..ec946cda 100644 --- a/Test/irondafny0/xrefine1.dfy.expect +++ b/Test/irondafny0/xrefine1.dfy.expect @@ -1,5 +1,5 @@ -xrefine1.dfy(71,13): Error BP5002: A precondition for this call might not hold. -xrefine1.dfy[MainImpl](49,29): Related location: This is the precondition that might not hold. +xrefine1.dfy(71,12): Error BP5002: A precondition for this call might not hold. +xrefine1.dfy[MainImpl](49,28): Related location: This is the precondition that might not hold. Execution trace: (0,0): anon0 -- cgit v1.2.3 From 8a0df70ffb8d57d1bd210ce2e1c9522ba0967365 Mon Sep 17 00:00:00 2001 From: Clément Pit--Claudel Date: Tue, 18 Aug 2015 18:58:40 -0700 Subject: Refactor the error reporting code The new error reporting system has a simpler interface, isn't tied to the resolver, and contains error source information. --- Source/Dafny/Cloner.cs | 33 +- Source/Dafny/Dafny.atg | 6 +- Source/Dafny/DafnyAst.cs | 20 +- Source/Dafny/DafnyMain.cs | 12 +- Source/Dafny/DafnyPipeline.csproj | 7 +- Source/Dafny/Parser.cs | 34 +- Source/Dafny/RefinementTransformer.cs | 293 ++++---- Source/Dafny/Reporting.cs | 164 +++++ Source/Dafny/Resolver.cs | 1146 +++++++++++++---------------- Source/Dafny/Rewriter.cs | 119 ++- Source/Dafny/Scanner.cs | 18 +- Source/Dafny/Translator.cs | 15 +- Source/Dafny/TriggerGenerator.cs | 4 +- Source/Dafny/Util.cs | 23 - Source/DafnyDriver/DafnyDriver.cs | 35 +- Source/DafnyExtension/DafnyDriver.cs | 77 +- Source/DafnyExtension/IdentifierTagger.cs | 4 +- Source/DafnyExtension/ResolverTagger.cs | 4 +- Source/DafnyServer/DafnyHelper.cs | 17 +- 19 files changed, 1006 insertions(+), 1025 deletions(-) create mode 100644 Source/Dafny/Reporting.cs (limited to 'Source/DafnyDriver/DafnyDriver.cs') diff --git a/Source/Dafny/Cloner.cs b/Source/Dafny/Cloner.cs index f959b537..323abc70 100644 --- a/Source/Dafny/Cloner.cs +++ b/Source/Dafny/Cloner.cs @@ -365,6 +365,7 @@ namespace Microsoft.Dafny return new NamedExpr(Tok(e.tok), e.Name, CloneExpr(e.Body)); } else if (expr is ComprehensionExpr) { var e = (ComprehensionExpr)expr; + var tk = Tok(e.tok); var bvs = e.BoundVars.ConvertAll(CloneBoundVar); var range = CloneExpr(e.Range); @@ -703,22 +704,16 @@ namespace Microsoft.Dafny abstract class FixpointCloner : Cloner { protected readonly Expression k; - readonly Resolver resolver; + protected readonly ErrorReporter reporter; readonly string suffix; - protected FixpointCloner(Expression k, Resolver resolver) + protected FixpointCloner(Expression k, ErrorReporter reporter) { Contract.Requires(k != null); - Contract.Requires(resolver != null); + Contract.Requires(reporter != null); this.k = k; - this.resolver = resolver; + this.reporter = reporter; this.suffix = string.Format("#[{0}]", Printer.ExprToString(k)); } - protected void ReportAdditionalInformation(IToken tok, string s) - { - Contract.Requires(tok != null); - Contract.Requires(s != null); - resolver.ReportAdditionalInformation(tok, s + suffix, s.Length); - } } /// @@ -733,12 +728,12 @@ namespace Microsoft.Dafny { readonly bool isCoContext; readonly ISet friendlyCalls; - public FixpointLemmaSpecificationSubstituter(ISet friendlyCalls, Expression k, Resolver resolver, bool isCoContext) - : base(k, resolver) + public FixpointLemmaSpecificationSubstituter(ISet friendlyCalls, Expression k, ErrorReporter reporter, bool isCoContext) + : base(k, reporter) { Contract.Requires(friendlyCalls != null); Contract.Requires(k != null); - Contract.Requires(resolver != null); + Contract.Requires(reporter != null); this.isCoContext = isCoContext; this.friendlyCalls = friendlyCalls; } @@ -758,7 +753,7 @@ namespace Microsoft.Dafny args.Add(CloneExpr(arg)); } var fexp = new FunctionCallExpr(Tok(e.tok), e.Name + "#", receiver, e.OpenParen, args); - ReportAdditionalInformation(e.tok, e.Name); + reporter.Info(MessageSource.Cloner, e.tok, e.Name); return fexp; } } else if (expr is BinaryExpr && isCoContext) { @@ -769,7 +764,7 @@ namespace Microsoft.Dafny var B = CloneExpr(e.E1); var teq = new TernaryExpr(Tok(e.tok), op, k, A, B); var opString = op == TernaryExpr.Opcode.PrefixEqOp ? "==" : "!="; - ReportAdditionalInformation(e.tok, opString); + reporter.Info(MessageSource.Cloner, e.tok, opString); return teq; } } @@ -804,12 +799,12 @@ namespace Microsoft.Dafny class FixpointLemmaBodyCloner : FixpointCloner { readonly FixpointLemma context; - public FixpointLemmaBodyCloner(FixpointLemma context, Expression k, Resolver resolver) - : base(k, resolver) + public FixpointLemmaBodyCloner(FixpointLemma context, Expression k, ErrorReporter reporter) + : base(k, reporter) { Contract.Requires(context != null); Contract.Requires(k != null); - Contract.Requires(resolver != null); + Contract.Requires(reporter != null); this.context = context; } public override AssignmentRhs CloneRHS(AssignmentRhs rhs) { @@ -834,7 +829,7 @@ namespace Microsoft.Dafny apply.Args.ForEach(arg => args.Add(CloneExpr(arg))); var applyClone = new ApplySuffix(Tok(apply.tok), lhsClone, args); var c = new ExprRhs(applyClone); - ReportAdditionalInformation(apply.tok, mse.Member.Name); + reporter.Info(MessageSource.Cloner, apply.tok, mse.Member.Name); return c; } } diff --git a/Source/Dafny/Dafny.atg b/Source/Dafny/Dafny.atg index 8a3bdb0e..07f8e1c4 100644 --- a/Source/Dafny/Dafny.atg +++ b/Source/Dafny/Dafny.atg @@ -55,11 +55,11 @@ public static int Parse (string/*!*/ filename, ModuleDecl module, BuiltIns built /// Returns the number of parsing errors encountered. /// Note: first initialize the Scanner. /// -public static int Parse (string/*!*/ s, string/*!*/ fullFilename, string/*!*/ filename, ModuleDecl module, BuiltIns builtIns, bool verifyThisFile=true) { +public static int Parse (string/*!*/ s, string/*!*/ fullFilename, string/*!*/ filename, ModuleDecl module, BuiltIns builtIns, ErrorReporter reporter, bool verifyThisFile=true) { Contract.Requires(s != null); Contract.Requires(filename != null); Contract.Requires(module != null); - Errors errors = new Errors(); + Errors errors = new Errors(reporter); return Parse(s, fullFilename, filename, module, builtIns, errors, verifyThisFile); } /// @@ -79,7 +79,7 @@ public static int Parse (string/*!*/ s, string/*!*/ fullFilename, string/*!*/ fi Scanner scanner = new Scanner(ms, errors, fullFilename, filename); Parser parser = new Parser(scanner, errors, module, builtIns, verifyThisFile); parser.Parse(); - return parser.errors.count; + return parser.errors.ErrorCount; } public Parser(Scanner/*!*/ scanner, Errors/*!*/ errors, ModuleDecl module, BuiltIns builtIns, bool verifyThisFile=true) : this(scanner, errors) // the real work diff --git a/Source/Dafny/DafnyAst.cs b/Source/Dafny/DafnyAst.cs index 66b91ac2..efe94c66 100644 --- a/Source/Dafny/DafnyAst.cs +++ b/Source/Dafny/DafnyAst.cs @@ -27,20 +27,22 @@ namespace Microsoft.Dafny { public List CompileModules; // filled in during resolution. // Contains the definitions to be used for compilation. - List _additionalInformation = new List(); - public List AdditionalInformation { get { return _additionalInformation; } } public readonly ModuleDecl DefaultModule; public readonly ModuleDefinition DefaultModuleDef; public readonly BuiltIns BuiltIns; public readonly List TranslationTasks; - public Program(string name, [Captured] ModuleDecl module, [Captured] BuiltIns builtIns) { + public readonly ErrorReporter reporter; + + public Program(string name, [Captured] ModuleDecl module, [Captured] BuiltIns builtIns, ErrorReporter reporter) { Contract.Requires(name != null); Contract.Requires(module != null); Contract.Requires(module is LiteralModuleDecl); + Contract.Requires(reporter != null); FullName = name; DefaultModule = module; DefaultModuleDef = (DefaultModuleDecl)((LiteralModuleDecl)module).ModuleDef; BuiltIns = builtIns; + this.reporter = reporter; Modules = new List(); CompileModules = new List(); TranslationTasks = new List(); @@ -330,13 +332,13 @@ namespace Microsoft.Dafny { /// - if "allowed" contains Int and Args contains one BigInteger literal, return true and set value to the BigInteger literal. Otherwise, /// - if "allowed" contains String and Args contains one string literal, return true and set value to the string literal. Otherwise, /// - if "allowed" contains Expression and Args contains one element, return true and set value to the one element (of type Expression). Otherwise, - /// - return false, leave value unmodified, and call errorReporter with an error string. + /// - return false, leave value unmodified, and call reporter with an error string. /// public enum MatchingValueOption { Empty, Bool, Int, String, Expression } - public static bool ContainsMatchingValue(Attributes attrs, string nm, ref object value, IEnumerable allowed, Action errorReporter) { + public static bool ContainsMatchingValue(Attributes attrs, string nm, ref object value, IEnumerable allowed, Action reporter) { Contract.Requires(nm != null); Contract.Requires(allowed != null); - Contract.Requires(errorReporter != null); + Contract.Requires(reporter != null); List args = FindExpressions(attrs, nm); if (args == null) { return false; @@ -344,7 +346,7 @@ namespace Microsoft.Dafny { if (allowed.Contains(MatchingValueOption.Empty)) { return true; } else { - errorReporter("Attribute " + nm + " requires one argument"); + reporter("Attribute " + nm + " requires one argument"); return false; } } else if (args.Count == 1) { @@ -364,11 +366,11 @@ namespace Microsoft.Dafny { value = arg; return true; } else { - errorReporter("Attribute " + nm + " expects an argument in one of the following categories: " + String.Join(", ", allowed)); + reporter("Attribute " + nm + " expects an argument in one of the following categories: " + String.Join(", ", allowed)); return false; } } else { - errorReporter("Attribute " + nm + " cannot have more than one argument"); + reporter("Attribute " + nm + " cannot have more than one argument"); return false; } } diff --git a/Source/Dafny/DafnyMain.cs b/Source/Dafny/DafnyMain.cs index 012ca4df..251d8656 100644 --- a/Source/Dafny/DafnyMain.cs +++ b/Source/Dafny/DafnyMain.cs @@ -29,7 +29,7 @@ namespace Microsoft.Dafny { /// /// Returns null on success, or an error string otherwise. /// - public static string ParseCheck(IList/*!*/ fileNames, string/*!*/ programName, out Program program) + public static string ParseCheck(IList/*!*/ fileNames, string/*!*/ programName, ErrorReporter reporter, out Program program) //modifies Bpl.CommandLineOptions.Clo.XmlSink.*; { Contract.Requires(programName != null); @@ -47,20 +47,20 @@ namespace Microsoft.Dafny { Console.WriteLine("Parsing " + dafnyFileName); } - string err = ParseFile(dafnyFileName, Bpl.Token.NoToken, module, builtIns, new Errors()); + string err = ParseFile(dafnyFileName, Bpl.Token.NoToken, module, builtIns, new Errors(reporter)); if (err != null) { return err; } } if (!DafnyOptions.O.DisallowIncludes) { - string errString = ParseIncludes(module, builtIns, fileNames, new Errors()); + string errString = ParseIncludes(module, builtIns, fileNames, new Errors(reporter)); if (errString != null) { return errString; } } - program = new Program(programName, module, builtIns); + program = new Program(programName, module, builtIns, reporter); MaybePrintProgram(program, DafnyOptions.O.DafnyPrintFile); @@ -70,8 +70,8 @@ namespace Microsoft.Dafny { r.ResolveProgram(program); MaybePrintProgram(program, DafnyOptions.O.DafnyPrintResolvedFile); - if (r.ErrorCount != 0) { - return string.Format("{0} resolution/type errors detected in {1}", r.ErrorCount, program.Name); + if (reporter.Count(ErrorLevel.Error) != 0) { + return string.Format("{0} resolution/type errors detected in {1}", reporter.Count(ErrorLevel.Error), program.Name); } return null; // success diff --git a/Source/Dafny/DafnyPipeline.csproj b/Source/Dafny/DafnyPipeline.csproj index a1452b8a..626bb26a 100644 --- a/Source/Dafny/DafnyPipeline.csproj +++ b/Source/Dafny/DafnyPipeline.csproj @@ -1,4 +1,4 @@ - + Debug @@ -8,7 +8,7 @@ {FE44674A-1633-4917-99F4-57635E6FA740} Library Properties - DafnyPipeline + Microsoft.Dafny DafnyPipeline v4.0 512 @@ -143,6 +143,7 @@ + @@ -193,4 +194,4 @@ --> - \ No newline at end of file + diff --git a/Source/Dafny/Parser.cs b/Source/Dafny/Parser.cs index fd6fb026..2507cacc 100644 --- a/Source/Dafny/Parser.cs +++ b/Source/Dafny/Parser.cs @@ -126,11 +126,11 @@ public static int Parse (string/*!*/ filename, ModuleDecl module, BuiltIns built /// Returns the number of parsing errors encountered. /// Note: first initialize the Scanner. /// -public static int Parse (string/*!*/ s, string/*!*/ fullFilename, string/*!*/ filename, ModuleDecl module, BuiltIns builtIns, bool verifyThisFile=true) { +public static int Parse (string/*!*/ s, string/*!*/ fullFilename, string/*!*/ filename, ModuleDecl module, BuiltIns builtIns, ErrorReporter reporter, bool verifyThisFile=true) { Contract.Requires(s != null); Contract.Requires(filename != null); Contract.Requires(module != null); - Errors errors = new Errors(); + Errors errors = new Errors(reporter); return Parse(s, fullFilename, filename, module, builtIns, errors, verifyThisFile); } /// @@ -150,7 +150,7 @@ public static int Parse (string/*!*/ s, string/*!*/ fullFilename, string/*!*/ fi Scanner scanner = new Scanner(ms, errors, fullFilename, filename); Parser parser = new Parser(scanner, errors, module, builtIns, verifyThisFile); parser.Parse(); - return parser.errors.count; + return parser.errors.ErrorCount; } public Parser(Scanner/*!*/ scanner, Errors/*!*/ errors, ModuleDecl module, BuiltIns builtIns, bool verifyThisFile=true) : this(scanner, errors) // the real work @@ -4426,16 +4426,22 @@ List/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo public class Errors { - public int count = 0; // number of errors detected + readonly ErrorReporter reporter; + public int ErrorCount; + + public Errors(ErrorReporter reporter) { + Contract.Requires(reporter != null); + this.reporter = reporter; + } public void SynErr(string filename, int line, int col, int n) { SynErr(filename, line, col, GetSyntaxErrorString(n)); } - public virtual void SynErr(string filename, int line, int col, string msg) { + public void SynErr(string filename, int line, int col, string msg) { Contract.Requires(msg != null); - Dafny.Util.ReportIssue("Error", filename, line, col, msg); - count++; + ErrorCount++; + reporter.Error(MessageSource.Parser, filename, line, col, msg); } string GetSyntaxErrorString(int n) { @@ -4692,20 +4698,20 @@ public class Errors { public void SemErr(IToken tok, string msg) { // semantic errors Contract.Requires(tok != null); Contract.Requires(msg != null); - Dafny.Util.ReportIssue("Error", tok, msg); - count++; + ErrorCount++; + reporter.Error(MessageSource.Parser, tok, msg); } - public virtual void SemErr(string filename, int line, int col, string msg) { + public void SemErr(string filename, int line, int col, string msg) { Contract.Requires(msg != null); - Dafny.Util.ReportIssue("Error", filename, line, col, msg); - count++; + ErrorCount++; + reporter.Error(MessageSource.Parser, filename, line, col, msg); } - public virtual void Warning(IToken tok, string msg) { // warnings + public void Warning(IToken tok, string msg) { Contract.Requires(tok != null); Contract.Requires(msg != null); - Dafny.Util.ReportIssue("Warning", tok, msg); + reporter.Warning(MessageSource.Parser, tok, msg); } } // Errors diff --git a/Source/Dafny/RefinementTransformer.cs b/Source/Dafny/RefinementTransformer.cs index f430933b..ba558ea6 100644 --- a/Source/Dafny/RefinementTransformer.cs +++ b/Source/Dafny/RefinementTransformer.cs @@ -52,16 +52,19 @@ namespace Microsoft.Dafny public class RefinementTransformer : IRewriter { - ResolutionErrorReporter reporter; - Action additionalInformationReporter; Cloner rawCloner; // This cloner just gives exactly the same thing back. RefinementCloner refinementCloner; // This cloner wraps things in a RefinementTransformer + Program program; - public RefinementTransformer(ResolutionErrorReporter reporter, Action additionalInformationReporter, Program p) { - Contract.Requires(reporter != null); - this.reporter = reporter; - this.additionalInformationReporter = additionalInformationReporter; + + public RefinementTransformer(ErrorReporter reporter) + : base(reporter) { rawCloner = new Cloner(); + } + + public RefinementTransformer(Program p) + : this(p.reporter) { + Contract.Requires(p != null); program = p; } @@ -71,17 +74,7 @@ namespace Microsoft.Dafny private Method currentMethod; public ModuleSignature RefinedSig; // the intention is to use this field only after a successful PreResolve - void ReportAdditionalInformation(IToken token, string text, int length) - { - Contract.Requires(token != null); - Contract.Requires(text != null); - Contract.Requires(0 <= length); - if (additionalInformationReporter != null) { - additionalInformationReporter(new AdditionalInformation { Token = token, Text = text, Length = length }); - } - } - - public void PreResolve(ModuleDefinition m) { + internal override void PreResolve(ModuleDefinition m) { if (m.RefinementBaseRoot != null) { if (Resolver.ResolvePath(m.RefinementBaseRoot, m.RefinementBaseName, out RefinedSig, reporter)) { if (RefinedSig.ModuleDef != null) { @@ -90,17 +83,17 @@ namespace Microsoft.Dafny if (null == m.RefinementBase.ExclusiveRefinement) { m.RefinementBase.ExclusiveRefinement = m; } else { - this.reporter.Error( + reporter.Error(MessageSource.RefinementTransformer, m.tok, "no more than one exclusive refinement may exist for a given module."); } } PreResolveWorker(m); } else { - reporter.Error(m.RefinementBaseName[0], "module ({0}) named as refinement base is not a literal module or simple reference to a literal module", Util.Comma(".", m.RefinementBaseName, x => x.val)); + reporter.Error(MessageSource.RefinementTransformer, m.RefinementBaseName[0], "module ({0}) named as refinement base is not a literal module or simple reference to a literal module", Util.Comma(".", m.RefinementBaseName, x => x.val)); } } else { - reporter.Error(m.RefinementBaseName[0], "module ({0}) named as refinement base does not exist", Util.Comma(".", m.RefinementBaseName, x => x.val)); + reporter.Error(MessageSource.RefinementTransformer, m.RefinementBaseName[0], "module ({0}) named as refinement base does not exist", Util.Comma(".", m.RefinementBaseName, x => x.val)); } } } @@ -135,9 +128,9 @@ namespace Microsoft.Dafny var nw = m.TopLevelDecls[index]; if (d is ModuleDecl) { if (!(nw is ModuleDecl)) { - reporter.Error(nw, "a module ({0}) must refine another module", nw.Name); + reporter.Error(MessageSource.RefinementTransformer, nw, "a module ({0}) must refine another module", nw.Name); } else if (!(d is ModuleFacadeDecl)) { - reporter.Error(nw, "a module ({0}) can only refine a module facade", nw.Name); + reporter.Error(MessageSource.RefinementTransformer, nw, "a module ({0}) can only refine a module facade", nw.Name); } else { ModuleSignature original = ((ModuleFacadeDecl)d).OriginalSignature; ModuleSignature derived = null; @@ -146,72 +139,72 @@ namespace Microsoft.Dafny } else if (nw is ModuleFacadeDecl) { derived = ((ModuleFacadeDecl)nw).Signature; } else { - reporter.Error(nw, "a module ({0}) can only be refined by an alias module or a module facade", d.Name); + reporter.Error(MessageSource.RefinementTransformer, nw, "a module ({0}) can only be refined by an alias module or a module facade", d.Name); } if (derived != null) { // check that the new module refines the previous declaration if (!CheckIsRefinement(derived, original)) - reporter.Error(nw.tok, "a module ({0}) can only be replaced by a refinement of the original module", d.Name); + reporter.Error(MessageSource.RefinementTransformer, nw.tok, "a module ({0}) can only be replaced by a refinement of the original module", d.Name); } } } else if (d is OpaqueTypeDecl) { if (nw is ModuleDecl) { - reporter.Error(nw, "a module ({0}) must refine another module", nw.Name); + reporter.Error(MessageSource.RefinementTransformer, nw, "a module ({0}) must refine another module", nw.Name); } else { bool dDemandsEqualitySupport = ((OpaqueTypeDecl)d).MustSupportEquality; if (nw is OpaqueTypeDecl) { if (dDemandsEqualitySupport != ((OpaqueTypeDecl)nw).MustSupportEquality) { - reporter.Error(nw, "type declaration '{0}' is not allowed to change the requirement of supporting equality", nw.Name); + reporter.Error(MessageSource.RefinementTransformer, nw, "type declaration '{0}' is not allowed to change the requirement of supporting equality", nw.Name); } if (nw.TypeArgs.Count != d.TypeArgs.Count) { - reporter.Error(nw, "type '{0}' is not allowed to change its number of type parameters (got {1}, expected {2})", nw.Name, nw.TypeArgs.Count, d.TypeArgs.Count); + reporter.Error(MessageSource.RefinementTransformer, nw, "type '{0}' is not allowed to change its number of type parameters (got {1}, expected {2})", nw.Name, nw.TypeArgs.Count, d.TypeArgs.Count); } } else if (dDemandsEqualitySupport) { if (nw is ClassDecl) { // fine, as long as "nw" takes the right number of type parameters if (nw.TypeArgs.Count != d.TypeArgs.Count) { - reporter.Error(nw, "opaque type '{0}' is not allowed to be replaced by a class that takes a different number of type parameters (got {1}, expected {2})", nw.Name, nw.TypeArgs.Count, d.TypeArgs.Count); + reporter.Error(MessageSource.RefinementTransformer, nw, "opaque type '{0}' is not allowed to be replaced by a class that takes a different number of type parameters (got {1}, expected {2})", nw.Name, nw.TypeArgs.Count, d.TypeArgs.Count); } } else if (nw is NewtypeDecl) { // fine, as long as "nw" does not take any type parameters if (nw.TypeArgs.Count != 0) { - reporter.Error(nw, "opaque type '{0}', which has {1} type argument{2}, is not allowed to be replaced by a newtype, which takes none", nw.Name, d.TypeArgs.Count, d.TypeArgs.Count == 1 ? "" : "s"); + reporter.Error(MessageSource.RefinementTransformer, nw, "opaque type '{0}', which has {1} type argument{2}, is not allowed to be replaced by a newtype, which takes none", nw.Name, d.TypeArgs.Count, d.TypeArgs.Count == 1 ? "" : "s"); } } else if (nw is CoDatatypeDecl) { - reporter.Error(nw, "a type declaration that requires equality support cannot be replaced by a codatatype"); + reporter.Error(MessageSource.RefinementTransformer, nw, "a type declaration that requires equality support cannot be replaced by a codatatype"); } else { Contract.Assert(nw is IndDatatypeDecl || nw is TypeSynonymDecl); if (nw.TypeArgs.Count != d.TypeArgs.Count) { - reporter.Error(nw, "opaque type '{0}' is not allowed to be replaced by a type that takes a different number of type parameters (got {1}, expected {2})", nw.Name, nw.TypeArgs.Count, d.TypeArgs.Count); + reporter.Error(MessageSource.RefinementTransformer, nw, "opaque type '{0}' is not allowed to be replaced by a type that takes a different number of type parameters (got {1}, expected {2})", nw.Name, nw.TypeArgs.Count, d.TypeArgs.Count); } else { // Here, we need to figure out if the new type supports equality. But we won't know about that until resolution has // taken place, so we defer it until the PostResolve phase. var udt = UserDefinedType.FromTopLevelDecl(nw.tok, nw); postTasks.Enqueue(() => { if (!udt.SupportsEquality) { - reporter.Error(udt.tok, "type '{0}' is used to refine an opaque type with equality support, but '{0}' does not support equality", udt.Name); + reporter.Error(MessageSource.RefinementTransformer, udt.tok, "type '{0}' is used to refine an opaque type with equality support, but '{0}' does not support equality", udt.Name); } }); } } } else if (d.TypeArgs.Count != nw.TypeArgs.Count) { - reporter.Error(nw, "opaque type '{0}' is not allowed to be replaced by a type that takes a different number of type parameters (got {1}, expected {2})", nw.Name, nw.TypeArgs.Count, d.TypeArgs.Count); + reporter.Error(MessageSource.RefinementTransformer, nw, "opaque type '{0}' is not allowed to be replaced by a type that takes a different number of type parameters (got {1}, expected {2})", nw.Name, nw.TypeArgs.Count, d.TypeArgs.Count); } } } else if (nw is OpaqueTypeDecl) { - reporter.Error(nw, "an opaque type declaration ({0}) in a refining module cannot replace a more specific type declaration in the refinement base", nw.Name); + reporter.Error(MessageSource.RefinementTransformer, nw, "an opaque type declaration ({0}) in a refining module cannot replace a more specific type declaration in the refinement base", nw.Name); } else if (nw is DatatypeDecl) { - reporter.Error(nw, "a datatype declaration ({0}) in a refinement module can only replace an opaque type declaration", nw.Name); + reporter.Error(MessageSource.RefinementTransformer, nw, "a datatype declaration ({0}) in a refinement module can only replace an opaque type declaration", nw.Name); } else if (nw is IteratorDecl) { if (d is IteratorDecl) { m.TopLevelDecls[index] = MergeIterator((IteratorDecl)nw, (IteratorDecl)d); } else { - reporter.Error(nw, "an iterator declaration ({0}) is a refining module cannot replace a different kind of declaration in the refinement base", nw.Name); + reporter.Error(MessageSource.RefinementTransformer, nw, "an iterator declaration ({0}) is a refining module cannot replace a different kind of declaration in the refinement base", nw.Name); } } else { Contract.Assert(nw is ClassDecl); if (d is DatatypeDecl) { - reporter.Error(nw, "a class declaration ({0}) in a refining module cannot replace a different kind of declaration in the refinement base", nw.Name); + reporter.Error(MessageSource.RefinementTransformer, nw, "a class declaration ({0}) in a refining module cannot replace a different kind of declaration in the refinement base", nw.Name); } else { m.TopLevelDecls[index] = MergeClass((ClassDecl)nw, (ClassDecl)d); } @@ -238,42 +231,42 @@ namespace Microsoft.Dafny // Second, we need to determine whether the specifications will be compatible // (i.e. substitutable), by translating to Boogie. - var errorCount = reporter.ErrorCount; + var errorCount = reporter.Count(ErrorLevel.Error); foreach (var kv in original.TopLevels) { var d = kv.Value; TopLevelDecl nw; if (derived.TopLevels.TryGetValue(kv.Key, out nw)) { if (d is ModuleDecl) { if (!(nw is ModuleDecl)) { - reporter.Error(nw, "a module ({0}) must refine another module", nw.Name); + reporter.Error(MessageSource.RefinementTransformer, nw, "a module ({0}) must refine another module", nw.Name); } else { CheckIsRefinement(((ModuleDecl)nw).Signature, ((ModuleDecl)d).Signature); } } else if (d is OpaqueTypeDecl) { if (nw is ModuleDecl) { - reporter.Error(nw, "a module ({0}) must refine another module", nw.Name); + reporter.Error(MessageSource.RefinementTransformer, nw, "a module ({0}) must refine another module", nw.Name); } else { bool dDemandsEqualitySupport = ((OpaqueTypeDecl)d).MustSupportEquality; if (nw is OpaqueTypeDecl) { if (dDemandsEqualitySupport != ((OpaqueTypeDecl)nw).MustSupportEquality) { - reporter.Error(nw, "type declaration '{0}' is not allowed to change the requirement of supporting equality", nw.Name); + reporter.Error(MessageSource.RefinementTransformer, nw, "type declaration '{0}' is not allowed to change the requirement of supporting equality", nw.Name); } } else if (dDemandsEqualitySupport) { if (nw is ClassDecl) { // fine, as long as "nw" does not take any type parameters if (nw.TypeArgs.Count != 0) { - reporter.Error(nw, "opaque type '{0}' is not allowed to be replaced by a class that takes type parameters", nw.Name); + reporter.Error(MessageSource.RefinementTransformer, nw, "opaque type '{0}' is not allowed to be replaced by a class that takes type parameters", nw.Name); } } else if (nw is CoDatatypeDecl) { - reporter.Error(nw, "a type declaration that requires equality support cannot be replaced by a codatatype"); + reporter.Error(MessageSource.RefinementTransformer, nw, "a type declaration that requires equality support cannot be replaced by a codatatype"); } else { Contract.Assert(nw is IndDatatypeDecl); if (nw.TypeArgs.Count != 0) { - reporter.Error(nw, "opaque type '{0}' is not allowed to be replaced by a datatype that takes type parameters", nw.Name); + reporter.Error(MessageSource.RefinementTransformer, nw, "opaque type '{0}' is not allowed to be replaced by a datatype that takes type parameters", nw.Name); } else { var udt = new UserDefinedType(nw.tok, nw.Name, nw, new List()); if (!(udt.SupportsEquality)) { - reporter.Error(nw.tok, "datatype '{0}' is used to refine an opaque type with equality support, but '{0}' does not support equality", nw.Name); + reporter.Error(MessageSource.RefinementTransformer, nw.tok, "datatype '{0}' is used to refine an opaque type with equality support, but '{0}' does not support equality", nw.Name); } } } @@ -282,18 +275,18 @@ namespace Microsoft.Dafny } else if (d is DatatypeDecl) { if (nw is DatatypeDecl) { if (d is IndDatatypeDecl && !(nw is IndDatatypeDecl)) { - reporter.Error(nw, "a datatype ({0}) must be replaced by a datatype, not a codatatype", d.Name); + reporter.Error(MessageSource.RefinementTransformer, nw, "a datatype ({0}) must be replaced by a datatype, not a codatatype", d.Name); } else if (d is CoDatatypeDecl && !(nw is CoDatatypeDecl)) { - reporter.Error(nw, "a codatatype ({0}) must be replaced by a codatatype, not a datatype", d.Name); + reporter.Error(MessageSource.RefinementTransformer, nw, "a codatatype ({0}) must be replaced by a codatatype, not a datatype", d.Name); } // check constructors, formals, etc. CheckDatatypesAreRefinements((DatatypeDecl)d, (DatatypeDecl)nw); } else { - reporter.Error(nw, "a {0} ({1}) must be refined by a {0}", d is IndDatatypeDecl ? "datatype" : "codatatype", d.Name); + reporter.Error(MessageSource.RefinementTransformer, nw, "a {0} ({1}) must be refined by a {0}", d is IndDatatypeDecl ? "datatype" : "codatatype", d.Name); } } else if (d is ClassDecl) { if (!(nw is ClassDecl)) { - reporter.Error(nw, "a class declaration ({0}) must be refined by another class declaration", nw.Name); + reporter.Error(MessageSource.RefinementTransformer, nw, "a class declaration ({0}) must be refined by another class declaration", nw.Name); } else { CheckClassesAreRefinements((ClassDecl)nw, (ClassDecl)d); } @@ -301,15 +294,15 @@ namespace Microsoft.Dafny Contract.Assert(false); throw new cce.UnreachableException(); // unexpected toplevel } } else { - reporter.Error(d, "declaration {0} must have a matching declaration in the refining module", d.Name); + reporter.Error(MessageSource.RefinementTransformer, d, "declaration {0} must have a matching declaration in the refining module", d.Name); } } - return errorCount == reporter.ErrorCount; + return errorCount == reporter.Count(ErrorLevel.Error); } private void CheckClassesAreRefinements(ClassDecl nw, ClassDecl d) { if (nw.TypeArgs.Count != d.TypeArgs.Count) { - reporter.Error(nw, "a refining class ({0}) must have the same number of type parameters", nw.Name); + reporter.Error(MessageSource.RefinementTransformer, nw, "a refining class ({0}) must have the same number of type parameters", nw.Name); } else { var map = new Dictionary(); foreach (var mem in nw.Members) { @@ -319,33 +312,33 @@ namespace Microsoft.Dafny MemberDecl newMem; if (map.TryGetValue(m.Name, out newMem)) { if (m.HasStaticKeyword != newMem.HasStaticKeyword) { - reporter.Error(newMem, "member {0} must {1}", m.Name, m.HasStaticKeyword ? "be static" : "not be static"); + reporter.Error(MessageSource.RefinementTransformer, newMem, "member {0} must {1}", m.Name, m.HasStaticKeyword ? "be static" : "not be static"); } if (m is Field) { if (newMem is Field) { var newField = (Field)newMem; if (!ResolvedTypesAreTheSame(newField.Type, ((Field)m).Type)) - reporter.Error(newMem, "field must be refined by a field with the same type (got {0}, expected {1})", newField.Type, ((Field)m).Type); + reporter.Error(MessageSource.RefinementTransformer, newMem, "field must be refined by a field with the same type (got {0}, expected {1})", newField.Type, ((Field)m).Type); if (m.IsGhost || !newField.IsGhost) - reporter.Error(newField, "a field re-declaration ({0}) must be to ghostify the field", newField.Name, nw.Name); + reporter.Error(MessageSource.RefinementTransformer, newField, "a field re-declaration ({0}) must be to ghostify the field", newField.Name, nw.Name); } else { - reporter.Error(newMem, "a field declaration ({1}) must be replaced by a field in the refinement base (not {0})", newMem.Name, nw.Name); + reporter.Error(MessageSource.RefinementTransformer, newMem, "a field declaration ({1}) must be replaced by a field in the refinement base (not {0})", newMem.Name, nw.Name); } } else if (m is Method) { if (newMem is Method) { CheckMethodsAreRefinements((Method)newMem, (Method)m); } else { - reporter.Error(newMem, "method must be refined by a method"); + reporter.Error(MessageSource.RefinementTransformer, newMem, "method must be refined by a method"); } } else if (m is Function) { if (newMem is Function) { CheckFunctionsAreRefinements((Function)newMem, (Function)m); } else { - reporter.Error(newMem, "{0} must be refined by a {0}", m.WhatKind); + reporter.Error(MessageSource.RefinementTransformer, newMem, "{0} must be refined by a {0}", m.WhatKind); } } } else { - reporter.Error(nw is DefaultClassDecl ? nw.Module.tok : nw.tok, "refining {0} must have member {1}", nw is DefaultClassDecl ? "module" : "class", m.Name); + reporter.Error(MessageSource.RefinementTransformer, nw is DefaultClassDecl ? nw.Module.tok : nw.tok, "refining {0} must have member {1}", nw is DefaultClassDecl ? "module" : "class", m.Name); } } } @@ -358,17 +351,17 @@ namespace Microsoft.Dafny Contract.Requires(thing != null); Contract.Requires(parameterKind != null); if (old.Count != nw.Count) { - reporter.Error(tok, "{0} '{1}' is declared with a different number of {2} ({3} instead of {4}) than the corresponding {0} in the module it refines", thing, name, parameterKind, nw.Count, old.Count); + reporter.Error(MessageSource.RefinementTransformer, tok, "{0} '{1}' is declared with a different number of {2} ({3} instead of {4}) than the corresponding {0} in the module it refines", thing, name, parameterKind, nw.Count, old.Count); } else { for (int i = 0; i < old.Count; i++) { var o = old[i]; var n = nw[i]; if (!o.IsGhost && n.IsGhost) { - reporter.Error(n.tok, "{0} '{1}' of {2} {3} cannot be changed, compared to the corresponding {2} in the module it refines, from non-ghost to ghost", parameterKind, n.Name, thing, name); + reporter.Error(MessageSource.RefinementTransformer, n.tok, "{0} '{1}' of {2} {3} cannot be changed, compared to the corresponding {2} in the module it refines, from non-ghost to ghost", parameterKind, n.Name, thing, name); } else if (o.IsGhost && !n.IsGhost) { - reporter.Error(n.tok, "{0} '{1}' of {2} {3} cannot be changed, compared to the corresponding {2} in the module it refines, from ghost to non-ghost", parameterKind, n.Name, thing, name); + reporter.Error(MessageSource.RefinementTransformer, n.tok, "{0} '{1}' of {2} {3} cannot be changed, compared to the corresponding {2} in the module it refines, from ghost to non-ghost", parameterKind, n.Name, thing, name); } else if (!ResolvedTypesAreTheSame(o.Type, n.Type)) { - reporter.Error(n.tok, "the type of {0} '{1}' is different from the type of the same {0} in the corresponding {2} in the module it refines ('{3}' instead of '{4}')", parameterKind, n.Name, thing, n.Type, o.Type); + reporter.Error(MessageSource.RefinementTransformer, n.tok, "the type of {0} '{1}' is different from the type of the same {0} in the corresponding {2} in the module it refines ('{3}' instead of '{4}')", parameterKind, n.Name, thing, n.Type, o.Type); } } } @@ -382,22 +375,22 @@ namespace Microsoft.Dafny private void CheckFunctionsAreRefinements(Function nw, Function f) { if (f is Predicate) { if (!(nw is Predicate)) { - reporter.Error(nw, "a predicate declaration ({0}) can only be refined by a predicate", nw.Name); + reporter.Error(MessageSource.RefinementTransformer, nw, "a predicate declaration ({0}) can only be refined by a predicate", nw.Name); } else { CheckAgreement_TypeParameters(nw.tok, f.TypeArgs, nw.TypeArgs, nw.Name, "predicate", false); CheckAgreementResolvedParameters(nw.tok, f.Formals, nw.Formals, nw.Name, "predicate", "parameter"); } } else if (f is FixpointPredicate) { - reporter.Error(nw, "refinement of {0}s is not supported", f.WhatKind); + reporter.Error(MessageSource.RefinementTransformer, nw, "refinement of {0}s is not supported", f.WhatKind); } else { // f is a plain Function if (nw is Predicate || nw is FixpointPredicate) { - reporter.Error(nw, "a {0} declaration ({1}) can only be refined by a function or function method", nw.IsGhost ? "function" : "function method", nw.Name); + reporter.Error(MessageSource.RefinementTransformer, nw, "a {0} declaration ({1}) can only be refined by a function or function method", nw.IsGhost ? "function" : "function method", nw.Name); } else { CheckAgreement_TypeParameters(nw.tok, f.TypeArgs, nw.TypeArgs, nw.Name, "function", false); CheckAgreementResolvedParameters(nw.tok, f.Formals, nw.Formals, nw.Name, "function", "parameter"); if (!ResolvedTypesAreTheSame(nw.ResultType, f.ResultType)) { - reporter.Error(nw, "the result type of function '{0}' ({1}) differs from the result type of the corresponding function in the module it refines ({2})", nw.Name, nw.ResultType, f.ResultType); + reporter.Error(MessageSource.RefinementTransformer, nw, "the result type of function '{0}' ({1}) differs from the result type of the corresponding function in the module it refines ({2})", nw.Name, nw.ResultType, f.ResultType); } } } @@ -408,7 +401,7 @@ namespace Microsoft.Dafny private void CheckDatatypesAreRefinements(DatatypeDecl dd, DatatypeDecl nn) { CheckAgreement_TypeParameters(nn.tok, dd.TypeArgs, nn.TypeArgs, dd.Name, "datatype", false); if (dd.Ctors.Count != nn.Ctors.Count) { - reporter.Error(nn.tok, "a refining datatype must have the same number of constructors"); + reporter.Error(MessageSource.RefinementTransformer, nn.tok, "a refining datatype must have the same number of constructors"); } else { var map = new Dictionary(); foreach (var ctor in nn.Ctors) { @@ -418,21 +411,21 @@ namespace Microsoft.Dafny DatatypeCtor newCtor; if (map.TryGetValue(ctor.Name, out newCtor)) { if (newCtor.Formals.Count != ctor.Formals.Count) { - reporter.Error(newCtor, "the constructor ({0}) must have the same number of formals as in the refined module", newCtor.Name); + reporter.Error(MessageSource.RefinementTransformer, newCtor, "the constructor ({0}) must have the same number of formals as in the refined module", newCtor.Name); } else { for (int i = 0; i < newCtor.Formals.Count; i++) { var a = ctor.Formals[i]; var b = newCtor.Formals[i]; if (a.HasName) { if (!b.HasName || a.Name != b.Name) - reporter.Error(b, "formal argument {0} in constructor {1} does not have the same name as in the refined module (should be {2})", i, ctor.Name, a.Name); + reporter.Error(MessageSource.RefinementTransformer, b, "formal argument {0} in constructor {1} does not have the same name as in the refined module (should be {2})", i, ctor.Name, a.Name); } if (!ResolvedTypesAreTheSame(a.Type, b.Type)) { - reporter.Error(b, "formal argument {0} in constructor {1} does not have the same type as in the refined module (should be {2}, not {3})", i, ctor.Name, a.Type.ToString(), b.Type.ToString()); + reporter.Error(MessageSource.RefinementTransformer, b, "formal argument {0} in constructor {1} does not have the same type as in the refined module (should be {2}, not {3})", i, ctor.Name, a.Type.ToString(), b.Type.ToString()); } } } } else { - reporter.Error(nn, "the constructor {0} must be present in the refining datatype", ctor.Name); + reporter.Error(MessageSource.RefinementTransformer, nn, "the constructor {0} must be present in the refining datatype", ctor.Name); } } } @@ -501,7 +494,8 @@ namespace Microsoft.Dafny Contract.Assert(false); throw new cce.UnreachableException(); // unexpected type } } - public void PostResolve(ModuleDefinition m) { + + internal override void PostResolve(ModuleDefinition m) { if (m == moduleUnderConstruction) { while (this.postTasks.Count != 0) { var a = postTasks.Dequeue(); @@ -512,8 +506,7 @@ namespace Microsoft.Dafny } moduleUnderConstruction = null; } - public void PostCyclicityResolve(ModuleDefinition m) { - } + Function CloneFunction(IToken tok, Function f, bool isGhost, List moreEnsures, Expression moreBody, Expression replacementBody, bool checkPrevPostconditions, Attributes moreAttributes) { Contract.Requires(tok != null); Contract.Requires(moreBody == null || f is Predicate); @@ -611,26 +604,26 @@ namespace Microsoft.Dafny Contract.Requires(prev != null); if (nw.Requires.Count != 0) { - reporter.Error(nw.Requires[0].E.tok, "a refining iterator is not allowed to add preconditions"); + reporter.Error(MessageSource.RefinementTransformer, nw.Requires[0].E.tok, "a refining iterator is not allowed to add preconditions"); } if (nw.YieldRequires.Count != 0) { - reporter.Error(nw.YieldRequires[0].E.tok, "a refining iterator is not allowed to add yield preconditions"); + reporter.Error(MessageSource.RefinementTransformer, nw.YieldRequires[0].E.tok, "a refining iterator is not allowed to add yield preconditions"); } if (nw.Reads.Expressions.Count != 0) { - reporter.Error(nw.Reads.Expressions[0].E.tok, "a refining iterator is not allowed to extend the reads clause"); + reporter.Error(MessageSource.RefinementTransformer, nw.Reads.Expressions[0].E.tok, "a refining iterator is not allowed to extend the reads clause"); } if (nw.Modifies.Expressions.Count != 0) { - reporter.Error(nw.Modifies.Expressions[0].E.tok, "a refining iterator is not allowed to extend the modifies clause"); + reporter.Error(MessageSource.RefinementTransformer, nw.Modifies.Expressions[0].E.tok, "a refining iterator is not allowed to extend the modifies clause"); } if (nw.Decreases.Expressions.Count != 0) { - reporter.Error(nw.Decreases.Expressions[0].tok, "a refining iterator is not allowed to extend the decreases clause"); + reporter.Error(MessageSource.RefinementTransformer, nw.Decreases.Expressions[0].tok, "a refining iterator is not allowed to extend the decreases clause"); } if (nw.SignatureIsOmitted) { Contract.Assert(nw.TypeArgs.Count == 0); Contract.Assert(nw.Ins.Count == 0); Contract.Assert(nw.Outs.Count == 0); - ReportAdditionalInformation(nw.SignatureEllipsis, Printer.IteratorSignatureToString(prev), 3); + reporter.Info(MessageSource.RefinementTransformer, nw.SignatureEllipsis, Printer.IteratorSignatureToString(prev)); } else { CheckAgreement_TypeParameters(nw.tok, prev.TypeArgs, nw.TypeArgs, nw.Name, "iterator"); CheckAgreement_Parameters(nw.tok, prev.Ins, nw.Ins, nw.Name, "iterator", "in-parameter"); @@ -694,9 +687,9 @@ namespace Microsoft.Dafny if (nwMember is Field) { if (member is Field && TypesAreSyntacticallyEqual(((Field)nwMember).Type, ((Field)member).Type)) { if (member.IsGhost || !nwMember.IsGhost) - reporter.Error(nwMember, "a field re-declaration ({0}) must be to ghostify the field", nwMember.Name, nw.Name); + reporter.Error(MessageSource.RefinementTransformer, nwMember, "a field re-declaration ({0}) must be to ghostify the field", nwMember.Name, nw.Name); } else { - reporter.Error(nwMember, "a field declaration ({0}) in a refining class ({1}) must replace a field in the refinement base", nwMember.Name, nw.Name); + reporter.Error(MessageSource.RefinementTransformer, nwMember, "a field declaration ({0}) in a refining class ({1}) must replace a field in the refinement base", nwMember.Name, nw.Name); } nwMember.RefinementBase = member; @@ -709,38 +702,38 @@ namespace Microsoft.Dafny (isPredicate && !(member is Predicate)) || (isIndPredicate && !(member is InductivePredicate)) || (isCoPredicate && !(member is CoPredicate))) { - reporter.Error(nwMember, "a {0} declaration ({1}) can only refine a {0}", f.WhatKind, nwMember.Name); + reporter.Error(MessageSource.RefinementTransformer, nwMember, "a {0} declaration ({1}) can only refine a {0}", f.WhatKind, nwMember.Name); } else if (f.IsProtected != ((Function)member).IsProtected) { - reporter.Error(f, "a {0} in a refinement module must be declared 'protected' if and only if the refined {0} is", f.WhatKind); + reporter.Error(MessageSource.RefinementTransformer, f, "a {0} in a refinement module must be declared 'protected' if and only if the refined {0} is", f.WhatKind); } else { var prevFunction = (Function)member; if (f.Req.Count != 0) { - reporter.Error(f.Req[0].tok, "a refining {0} is not allowed to add preconditions", f.WhatKind); + reporter.Error(MessageSource.RefinementTransformer, f.Req[0].tok, "a refining {0} is not allowed to add preconditions", f.WhatKind); } if (f.Reads.Count != 0) { - reporter.Error(f.Reads[0].E.tok, "a refining {0} is not allowed to extend the reads clause", f.WhatKind); + reporter.Error(MessageSource.RefinementTransformer, f.Reads[0].E.tok, "a refining {0} is not allowed to extend the reads clause", f.WhatKind); } if (f.Decreases.Expressions.Count != 0) { - reporter.Error(f.Decreases.Expressions[0].tok, "decreases clause on refining {0} not supported", f.WhatKind); + reporter.Error(MessageSource.RefinementTransformer, f.Decreases.Expressions[0].tok, "decreases clause on refining {0} not supported", f.WhatKind); } if (prevFunction.HasStaticKeyword != f.HasStaticKeyword) { - reporter.Error(f, "a function in a refining module cannot be changed from static to non-static or vice versa: {0}", f.Name); + reporter.Error(MessageSource.RefinementTransformer, f, "a function in a refining module cannot be changed from static to non-static or vice versa: {0}", f.Name); } if (!prevFunction.IsGhost && f.IsGhost) { - reporter.Error(f, "a function method cannot be changed into a (ghost) function in a refining module: {0}", f.Name); + reporter.Error(MessageSource.RefinementTransformer, f, "a function method cannot be changed into a (ghost) function in a refining module: {0}", f.Name); } else if (prevFunction.IsGhost && !f.IsGhost && prevFunction.Body != null) { - reporter.Error(f, "a function can be changed into a function method in a refining module only if the function has not yet been given a body: {0}", f.Name); + reporter.Error(MessageSource.RefinementTransformer, f, "a function can be changed into a function method in a refining module only if the function has not yet been given a body: {0}", f.Name); } if (f.SignatureIsOmitted) { Contract.Assert(f.TypeArgs.Count == 0); Contract.Assert(f.Formals.Count == 0); - ReportAdditionalInformation(f.SignatureEllipsis, Printer.FunctionSignatureToString(prevFunction), 3); + reporter.Info(MessageSource.RefinementTransformer, f.SignatureEllipsis, Printer.FunctionSignatureToString(prevFunction)); } else { CheckAgreement_TypeParameters(f.tok, prevFunction.TypeArgs, f.TypeArgs, f.Name, "function"); CheckAgreement_Parameters(f.tok, prevFunction.Formals, f.Formals, f.Name, "function", "parameter"); if (!TypesAreSyntacticallyEqual(prevFunction.ResultType, f.ResultType)) { - reporter.Error(f, "the result type of function '{0}' ({1}) differs from the result type of the corresponding function in the module it refines ({2})", f.Name, f.ResultType, prevFunction.ResultType); + reporter.Error(MessageSource.RefinementTransformer, f, "the result type of function '{0}' ({1}) differs from the result type of the corresponding function in the module it refines ({2})", f.Name, f.ResultType, prevFunction.ResultType); } } @@ -752,9 +745,9 @@ namespace Microsoft.Dafny if (isPredicate && f.IsProtected) { moreBody = f.Body; } else if (isPredicate) { - reporter.Error(nwMember, "a refining predicate is not allowed to extend/change the body unless it is declared 'protected'"); + reporter.Error(MessageSource.RefinementTransformer, nwMember, "a refining predicate is not allowed to extend/change the body unless it is declared 'protected'"); } else { - reporter.Error(nwMember, "a refining function is not allowed to extend/change the body"); + reporter.Error(MessageSource.RefinementTransformer, nwMember, "a refining function is not allowed to extend/change the body"); } } var newF = CloneFunction(f.tok, prevFunction, f.IsGhost, f.Ens, moreBody, replacementBody, prevFunction.Body == null, f.Attributes); @@ -765,14 +758,14 @@ namespace Microsoft.Dafny } else { var m = (Method)nwMember; if (!(member is Method)) { - reporter.Error(nwMember, "a method declaration ({0}) can only refine a method", nwMember.Name); + reporter.Error(MessageSource.RefinementTransformer, nwMember, "a method declaration ({0}) can only refine a method", nwMember.Name); } else { var prevMethod = (Method)member; if (m.Req.Count != 0) { - reporter.Error(m.Req[0].E.tok, "a refining method is not allowed to add preconditions"); + reporter.Error(MessageSource.RefinementTransformer, m.Req[0].E.tok, "a refining method is not allowed to add preconditions"); } if (m.Mod.Expressions.Count != 0) { - reporter.Error(m.Mod.Expressions[0].E.tok, "a refining method is not allowed to extend the modifies clause"); + reporter.Error(MessageSource.RefinementTransformer, m.Mod.Expressions[0].E.tok, "a refining method is not allowed to extend the modifies clause"); } // If the previous method was not specified with "decreases *", then the new method is not allowed to provide any "decreases" clause. // Any "decreases *" clause is not inherited, so if the previous method was specified with "decreases *", then the new method needs @@ -785,23 +778,23 @@ namespace Microsoft.Dafny } else { if (!Contract.Exists(prevMethod.Decreases.Expressions, e => e is WildcardExpr)) { // If the previous loop was not specified with "decreases *", then the new loop is not allowed to provide any "decreases" clause. - reporter.Error(m.Decreases.Expressions[0].tok, "decreases clause on refining method not supported, unless the refined method was specified with 'decreases *'"); + reporter.Error(MessageSource.RefinementTransformer, m.Decreases.Expressions[0].tok, "decreases clause on refining method not supported, unless the refined method was specified with 'decreases *'"); } decreases = m.Decreases; } if (prevMethod.HasStaticKeyword != m.HasStaticKeyword) { - reporter.Error(m, "a method in a refining module cannot be changed from static to non-static or vice versa: {0}", m.Name); + reporter.Error(MessageSource.RefinementTransformer, m, "a method in a refining module cannot be changed from static to non-static or vice versa: {0}", m.Name); } if (prevMethod.IsGhost && !m.IsGhost) { - reporter.Error(m, "a method cannot be changed into a ghost method in a refining module: {0}", m.Name); + reporter.Error(MessageSource.RefinementTransformer, m, "a method cannot be changed into a ghost method in a refining module: {0}", m.Name); } else if (!prevMethod.IsGhost && m.IsGhost) { - reporter.Error(m, "a ghost method cannot be changed into a non-ghost method in a refining module: {0}", m.Name); + reporter.Error(MessageSource.RefinementTransformer, m, "a ghost method cannot be changed into a non-ghost method in a refining module: {0}", m.Name); } if (m.SignatureIsOmitted) { Contract.Assert(m.TypeArgs.Count == 0); Contract.Assert(m.Ins.Count == 0); Contract.Assert(m.Outs.Count == 0); - ReportAdditionalInformation(m.SignatureEllipsis, Printer.MethodSignatureToString(prevMethod), 3); + reporter.Info(MessageSource.RefinementTransformer, m.SignatureEllipsis, Printer.MethodSignatureToString(prevMethod)); } else { CheckAgreement_TypeParameters(m.tok, prevMethod.TypeArgs, m.TypeArgs, m.Name, "method"); CheckAgreement_Parameters(m.tok, prevMethod.Ins, m.Ins, m.Name, "method", "in-parameter"); @@ -833,13 +826,13 @@ namespace Microsoft.Dafny Contract.Requires(name != null); Contract.Requires(thing != null); if (old.Count != nw.Count) { - reporter.Error(tok, "{0} '{1}' is declared with a different number of type parameters ({2} instead of {3}) than the corresponding {0} in the module it refines", thing, name, nw.Count, old.Count); + reporter.Error(MessageSource.RefinementTransformer, tok, "{0} '{1}' is declared with a different number of type parameters ({2} instead of {3}) than the corresponding {0} in the module it refines", thing, name, nw.Count, old.Count); } else { for (int i = 0; i < old.Count; i++) { var o = old[i]; var n = nw[i]; if (o.Name != n.Name && checkNames) { // if checkNames is false, then just treat the parameters positionally. - reporter.Error(n.tok, "type parameters are not allowed to be renamed from the names given in the {0} in the module being refined (expected '{1}', found '{2}')", thing, o.Name, n.Name); + reporter.Error(MessageSource.RefinementTransformer, n.tok, "type parameters are not allowed to be renamed from the names given in the {0} in the module being refined (expected '{1}', found '{2}')", thing, o.Name, n.Name); } else { // This explains what we want to do and why: // switch (o.EqualitySupport) { @@ -859,7 +852,7 @@ namespace Microsoft.Dafny // } // Here's how we actually compute it: if (o.EqualitySupport != TypeParameter.EqualitySupportValue.InferredRequired && o.EqualitySupport != n.EqualitySupport) { - reporter.Error(n.tok, "type parameter '{0}' is not allowed to change the requirement of supporting equality", n.Name); + reporter.Error(MessageSource.RefinementTransformer, n.tok, "type parameter '{0}' is not allowed to change the requirement of supporting equality", n.Name); } } } @@ -872,7 +865,7 @@ namespace Microsoft.Dafny CheckOverrideResolvedParameters(nw.tok, f.Formals, nw.Formals, nw.Name, "function", "parameter"); if (!ResolvedTypesAreTheSame(nw.ResultType, f.ResultType)) { - reporter.Error(nw, "the result type of function '{0}' ({1}) differs from the result type of the corresponding function in the module it overrides ({2})", nw.Name, nw.ResultType, f.ResultType); + reporter.Error(MessageSource.RefinementTransformer, nw, "the result type of function '{0}' ({1}) differs from the result type of the corresponding function in the module it overrides ({2})", nw.Name, nw.ResultType, f.ResultType); } } @@ -892,7 +885,7 @@ namespace Microsoft.Dafny Contract.Requires(thing != null); if (old.Count != nw.Count) { - reporter.Error(tok, "{0} '{1}' is declared with a different number of type parameters ({2} instead of {3}) than the corresponding {0} in the module it overrides", thing, name, nw.Count, old.Count); + reporter.Error(MessageSource.RefinementTransformer, tok, "{0} '{1}' is declared with a different number of type parameters ({2} instead of {3}) than the corresponding {0} in the module it overrides", thing, name, nw.Count, old.Count); } else { @@ -902,14 +895,14 @@ namespace Microsoft.Dafny var n = nw[i]; if (o.Name != n.Name && checkNames) { // if checkNames is false, then just treat the parameters positionally. - reporter.Error(n.tok, "type parameters are not allowed to be renamed from the names given in the {0} in the module being overriden (expected '{1}', found '{2}')", thing, o.Name, n.Name); + reporter.Error(MessageSource.RefinementTransformer, n.tok, "type parameters are not allowed to be renamed from the names given in the {0} in the module being overriden (expected '{1}', found '{2}')", thing, o.Name, n.Name); } else { // Here's how we actually compute it: if (o.EqualitySupport != TypeParameter.EqualitySupportValue.InferredRequired && o.EqualitySupport != n.EqualitySupport) { - reporter.Error(n.tok, "type parameter '{0}' is not allowed to change the requirement of supporting equality", n.Name); + reporter.Error(MessageSource.RefinementTransformer, n.tok, "type parameter '{0}' is not allowed to change the requirement of supporting equality", n.Name); } } } @@ -926,7 +919,7 @@ namespace Microsoft.Dafny Contract.Requires(parameterKind != null); if (old.Count != nw.Count) { - reporter.Error(tok, "{0} '{1}' is declared with a different number of {2} ({3} instead of {4}) than the corresponding {0} in the module it overrides", thing, name, parameterKind, nw.Count, old.Count); + reporter.Error(MessageSource.RefinementTransformer, tok, "{0} '{1}' is declared with a different number of {2} ({3} instead of {4}) than the corresponding {0} in the module it overrides", thing, name, parameterKind, nw.Count, old.Count); } else { @@ -936,15 +929,15 @@ namespace Microsoft.Dafny var n = nw[i]; if (!o.IsGhost && n.IsGhost) { - reporter.Error(n.tok, "{0} '{1}' of {2} {3} cannot be changed, compared to the corresponding {2} in the module it overrides, from non-ghost to ghost", parameterKind, n.Name, thing, name); + reporter.Error(MessageSource.RefinementTransformer, n.tok, "{0} '{1}' of {2} {3} cannot be changed, compared to the corresponding {2} in the module it overrides, from non-ghost to ghost", parameterKind, n.Name, thing, name); } else if (o.IsGhost && !n.IsGhost) { - reporter.Error(n.tok, "{0} '{1}' of {2} {3} cannot be changed, compared to the corresponding {2} in the module it overrides, from ghost to non-ghost", parameterKind, n.Name, thing, name); + reporter.Error(MessageSource.RefinementTransformer, n.tok, "{0} '{1}' of {2} {3} cannot be changed, compared to the corresponding {2} in the module it overrides, from ghost to non-ghost", parameterKind, n.Name, thing, name); } else if (!ResolvedTypesAreTheSame(o.Type, n.Type)) { - reporter.Error(n.tok, "the type of {0} '{1}' is different from the type of the same {0} in the corresponding {2} in the module it overrides ('{3}' instead of '{4}')", parameterKind, n.Name, thing, n.Type, o.Type); + reporter.Error(MessageSource.RefinementTransformer, n.tok, "the type of {0} '{1}' is different from the type of the same {0} in the corresponding {2} in the module it overrides ('{3}' instead of '{4}')", parameterKind, n.Name, thing, n.Type, o.Type); } } } @@ -958,19 +951,19 @@ namespace Microsoft.Dafny Contract.Requires(thing != null); Contract.Requires(parameterKind != null); if (old.Count != nw.Count) { - reporter.Error(tok, "{0} '{1}' is declared with a different number of {2} ({3} instead of {4}) than the corresponding {0} in the module it refines", thing, name, parameterKind, nw.Count, old.Count); + reporter.Error(MessageSource.RefinementTransformer, tok, "{0} '{1}' is declared with a different number of {2} ({3} instead of {4}) than the corresponding {0} in the module it refines", thing, name, parameterKind, nw.Count, old.Count); } else { for (int i = 0; i < old.Count; i++) { var o = old[i]; var n = nw[i]; if (o.Name != n.Name) { - reporter.Error(n.tok, "there is a difference in name of {0} {1} ('{2}' versus '{3}') of {4} {5} compared to corresponding {4} in the module it refines", parameterKind, i, n.Name, o.Name, thing, name); + reporter.Error(MessageSource.RefinementTransformer, n.tok, "there is a difference in name of {0} {1} ('{2}' versus '{3}') of {4} {5} compared to corresponding {4} in the module it refines", parameterKind, i, n.Name, o.Name, thing, name); } else if (!o.IsGhost && n.IsGhost) { - reporter.Error(n.tok, "{0} '{1}' of {2} {3} cannot be changed, compared to the corresponding {2} in the module it refines, from non-ghost to ghost", parameterKind, n.Name, thing, name); + reporter.Error(MessageSource.RefinementTransformer, n.tok, "{0} '{1}' of {2} {3} cannot be changed, compared to the corresponding {2} in the module it refines, from non-ghost to ghost", parameterKind, n.Name, thing, name); } else if (o.IsGhost && !n.IsGhost) { - reporter.Error(n.tok, "{0} '{1}' of {2} {3} cannot be changed, compared to the corresponding {2} in the module it refines, from ghost to non-ghost", parameterKind, n.Name, thing, name); + reporter.Error(MessageSource.RefinementTransformer, n.tok, "{0} '{1}' of {2} {3} cannot be changed, compared to the corresponding {2} in the module it refines, from ghost to non-ghost", parameterKind, n.Name, thing, name); } else if (!TypesAreSyntacticallyEqual(o.Type, n.Type)) { - reporter.Error(n.tok, "the type of {0} '{1}' is different from the type of the same {0} in the corresponding {2} in the module it refines ('{3}' instead of '{4}')", parameterKind, n.Name, thing, n.Type, o.Type); + reporter.Error(MessageSource.RefinementTransformer, n.tok, "the type of {0} '{1}' is different from the type of the same {0} in the corresponding {2} in the module it refines ('{3}' instead of '{4}')", parameterKind, n.Name, thing, n.Type, o.Type); } } } @@ -996,7 +989,7 @@ namespace Microsoft.Dafny } else if (((SkeletonStatement)cur).S == null) { // the "..." matches the empty statement sequence } else { - reporter.Error(cur.Tok, "skeleton statement does not match old statement"); + reporter.Error(MessageSource.RefinementTransformer, cur.Tok, "skeleton statement does not match old statement"); } i++; } else { @@ -1050,7 +1043,7 @@ namespace Microsoft.Dafny Contract.Assert(c.NameReplacements.Count == c.ExprReplacements.Count); for (int k = 0; k < c.NameReplacements.Count; k++) { if (subExprs.ContainsKey(c.NameReplacements[k].val)) { - reporter.Error(c.NameReplacements[k], "replacement definition must contain at most one definition for a given label"); + reporter.Error(MessageSource.RefinementTransformer, c.NameReplacements[k], "replacement definition must contain at most one definition for a given label"); } else subExprs.Add(c.NameReplacements[k].val, c.ExprReplacements[k]); } subber = new SubstitutionCloner(subExprs, rawCloner); @@ -1071,12 +1064,12 @@ namespace Microsoft.Dafny oldS = oldStmt.Body[j]; } if (hoverTextA.Length != 0) { - ReportAdditionalInformation(c.Tok, hoverTextA, 3); + reporter.Info(MessageSource.RefinementTransformer, c.Tok, hoverTextA); } if (subber != null && subber.SubstitutionsMade.Count < subber.Exprs.Count) { foreach (var s in subber.SubstitutionsMade) subber.Exprs.Remove(s); - reporter.Error(c.Tok, "could not find labeled expression(s): " + Util.Comma(", ", subber.Exprs.Keys, x => x)); + reporter.Error(MessageSource.RefinementTransformer, c.Tok, "could not find labeled expression(s): " + Util.Comma(", ", subber.Exprs.Keys, x => x)); } } i++; @@ -1086,7 +1079,7 @@ namespace Microsoft.Dafny Contract.Assert(c.ConditionOmitted); var oldAssume = oldS as PredicateStmt; if (oldAssume == null) { - reporter.Error(cur.Tok, "assert template does not match inherited statement"); + reporter.Error(MessageSource.RefinementTransformer, cur.Tok, "assert template does not match inherited statement"); i++; } else { // Clone the expression, but among the new assert's attributes, indicate @@ -1097,7 +1090,7 @@ namespace Microsoft.Dafny var attrs = refinementCloner.MergeAttributes(oldAssume.Attributes, skel.Attributes); body.Add(new AssertStmt(new Translator.ForceCheckToken(skel.Tok), new Translator.ForceCheckToken(skel.EndTok), e, new Attributes("prependAssertToken", new List(), attrs))); - ReportAdditionalInformation(c.ConditionEllipsis, "assume->assert: " + Printer.ExprToString(e), 3); + reporter.Info(MessageSource.RefinementTransformer, c.ConditionEllipsis, "assume->assert: " + Printer.ExprToString(e)); i++; j++; } @@ -1106,13 +1099,13 @@ namespace Microsoft.Dafny Contract.Assert(c.ConditionOmitted); var oldAssume = oldS as AssumeStmt; if (oldAssume == null) { - reporter.Error(cur.Tok, "assume template does not match inherited statement"); + reporter.Error(MessageSource.RefinementTransformer, cur.Tok, "assume template does not match inherited statement"); i++; } else { var e = refinementCloner.CloneExpr(oldAssume.Expr); var attrs = refinementCloner.MergeAttributes(oldAssume.Attributes, skel.Attributes); body.Add(new AssumeStmt(skel.Tok, skel.EndTok, e, attrs)); - ReportAdditionalInformation(c.ConditionEllipsis, Printer.ExprToString(e), 3); + reporter.Info(MessageSource.RefinementTransformer, c.ConditionEllipsis, Printer.ExprToString(e)); i++; j++; } @@ -1121,7 +1114,7 @@ namespace Microsoft.Dafny Contract.Assert(c.ConditionOmitted); var oldIf = oldS as IfStmt; if (oldIf == null) { - reporter.Error(cur.Tok, "if-statement template does not match inherited statement"); + reporter.Error(MessageSource.RefinementTransformer, cur.Tok, "if-statement template does not match inherited statement"); i++; } else { var resultingThen = MergeBlockStmt(skel.Thn, oldIf.Thn); @@ -1129,7 +1122,7 @@ namespace Microsoft.Dafny var e = refinementCloner.CloneExpr(oldIf.Guard); var r = new IfStmt(skel.Tok, skel.EndTok, e, resultingThen, resultingElse); body.Add(r); - ReportAdditionalInformation(c.ConditionEllipsis, Printer.GuardToString(e), 3); + reporter.Info(MessageSource.RefinementTransformer, c.ConditionEllipsis, Printer.GuardToString(e)); i++; j++; } @@ -1137,16 +1130,16 @@ namespace Microsoft.Dafny var skel = (WhileStmt)S; var oldWhile = oldS as WhileStmt; if (oldWhile == null) { - reporter.Error(cur.Tok, "while-statement template does not match inherited statement"); + reporter.Error(MessageSource.RefinementTransformer, cur.Tok, "while-statement template does not match inherited statement"); i++; } else { Expression guard; if (c.ConditionOmitted) { guard = refinementCloner.CloneExpr(oldWhile.Guard); - ReportAdditionalInformation(c.ConditionEllipsis, Printer.GuardToString(oldWhile.Guard), 3); + reporter.Info(MessageSource.RefinementTransformer, c.ConditionEllipsis, Printer.GuardToString(oldWhile.Guard)); } else { if (oldWhile.Guard != null) { - reporter.Error(skel.Guard.tok, "a skeleton while statement with a guard can only replace a while statement with a non-deterministic guard"); + reporter.Error(MessageSource.RefinementTransformer, skel.Guard.tok, "a skeleton while statement with a guard can only replace a while statement with a non-deterministic guard"); } guard = skel.Guard; } @@ -1162,7 +1155,7 @@ namespace Microsoft.Dafny Contract.Assert(c.ConditionOmitted); var oldModifyStmt = oldS as ModifyStmt; if (oldModifyStmt == null) { - reporter.Error(cur.Tok, "modify template does not match inherited statement"); + reporter.Error(MessageSource.RefinementTransformer, cur.Tok, "modify template does not match inherited statement"); i++; } else { var mod = refinementCloner.CloneSpecFrameExpr(oldModifyStmt.Mod); @@ -1172,13 +1165,13 @@ namespace Microsoft.Dafny } else if (oldModifyStmt.Body == null) { mbody = skel.Body; } else if (skel.Body == null) { - reporter.Error(cur.Tok, "modify template must have a body if the inherited modify statement does"); + reporter.Error(MessageSource.RefinementTransformer, cur.Tok, "modify template must have a body if the inherited modify statement does"); mbody = null; } else { mbody = MergeBlockStmt(skel.Body, oldModifyStmt.Body); } body.Add(new ModifyStmt(skel.Tok, skel.EndTok, mod.Expressions, mod.Attributes, mbody)); - ReportAdditionalInformation(c.ConditionEllipsis, Printer.FrameExprListToString(mod.Expressions), 3); + reporter.Info(MessageSource.RefinementTransformer, c.ConditionEllipsis, Printer.FrameExprListToString(mod.Expressions)); i++; j++; } @@ -1341,7 +1334,7 @@ namespace Microsoft.Dafny sep = "\n"; } if (hoverText.Length != 0) { - ReportAdditionalInformation(skeleton.EndTok, hoverText, 3); + reporter.Info(MessageSource.RefinementTransformer, skeleton.EndTok, hoverText); } return new BlockStmt(skeleton.Tok, skeleton.EndTok, body); } @@ -1447,7 +1440,7 @@ namespace Microsoft.Dafny } else { if (!Contract.Exists(cOld.Decreases.Expressions, e => e is WildcardExpr)) { // If the previous loop was not specified with "decreases *", then the new loop is not allowed to provide any "decreases" clause. - reporter.Error(cNew.Decreases.Expressions[0].tok, "a refining loop can provide a decreases clause only if the loop being refined was declared with 'decreases *'"); + reporter.Error(MessageSource.RefinementTransformer, cNew.Decreases.Expressions[0].tok, "a refining loop can provide a decreases clause only if the loop being refined was declared with 'decreases *'"); } decr = cNew.Decreases; } @@ -1489,9 +1482,9 @@ namespace Microsoft.Dafny void MergeAddStatement(Statement s, List stmtList) { Contract.Requires(s != null); Contract.Requires(stmtList != null); - var prevErrorCount = reporter.ErrorCount; + var prevErrorCount = reporter.Count(ErrorLevel.Error); CheckIsOkayNewStatement(s, new Stack(), 0); - if (reporter.ErrorCount == prevErrorCount) { + if (reporter.Count(ErrorLevel.Error) == prevErrorCount) { stmtList.Add(s); } } @@ -1508,30 +1501,30 @@ namespace Microsoft.Dafny labels.Push(n.Data.Name); } if (s is SkeletonStatement) { - reporter.Error(s, "skeleton statement may not be used here; it does not have a matching statement in what is being replaced"); + reporter.Error(MessageSource.RefinementTransformer, s, "skeleton statement may not be used here; it does not have a matching statement in what is being replaced"); } else if (s is ReturnStmt) { // allow return statements, but make note of that this requires verifying the postcondition ((ReturnStmt)s).ReverifyPost = true; } else if (s is YieldStmt) { - reporter.Error(s, "yield statements are not allowed in skeletons"); + reporter.Error(MessageSource.RefinementTransformer, s, "yield statements are not allowed in skeletons"); } else if (s is BreakStmt) { var b = (BreakStmt)s; if (b.TargetLabel != null ? !labels.Contains(b.TargetLabel) : loopLevels < b.BreakCount) { - reporter.Error(s, "break statement in skeleton is not allowed to break outside the skeleton fragment"); + reporter.Error(MessageSource.RefinementTransformer, s, "break statement in skeleton is not allowed to break outside the skeleton fragment"); } } else if (s is AssignStmt) { // TODO: To be a refinement automatically (that is, without any further verification), only variables and fields defined // in this module are allowed. This needs to be checked. If the LHS refers to an l-value that was not declared within // this module, then either an error should be reported or the Translator needs to know to translate new proof obligations. var a = (AssignStmt)s; - reporter.Error(a.Tok, "cannot have assignment statement"); + reporter.Error(MessageSource.RefinementTransformer, a.Tok, "cannot have assignment statement"); } else if (s is ConcreteUpdateStatement) { postTasks.Enqueue(() => { - CheckIsOkayUpdateStmt((ConcreteUpdateStatement)s, moduleUnderConstruction, reporter); + CheckIsOkayUpdateStmt((ConcreteUpdateStatement)s, moduleUnderConstruction); }); } else if (s is CallStmt) { - reporter.Error(s.Tok, "cannot have call statement"); + reporter.Error(MessageSource.RefinementTransformer, s.Tok, "cannot have call statement"); } else { if (s is WhileStmt || s is AlternativeLoopStmt) { loopLevels++; @@ -1547,7 +1540,7 @@ namespace Microsoft.Dafny } // Checks that statement stmt, defined in the constructed module m, is a refinement of skip in the parent module - void CheckIsOkayUpdateStmt(ConcreteUpdateStatement stmt, ModuleDefinition m, ResolutionErrorReporter reporter) { + void CheckIsOkayUpdateStmt(ConcreteUpdateStatement stmt, ModuleDefinition m) { foreach (var lhs in stmt.Lhss) { var l = lhs.Resolved; if (l is IdentifierExpr) { @@ -1555,23 +1548,23 @@ namespace Microsoft.Dafny Contract.Assert(ident.Var is LocalVariable || ident.Var is Formal); // LHS identifier expressions must be locals or out parameters (ie. formals) if ((ident.Var is LocalVariable && RefinementToken.IsInherited(((LocalVariable)ident.Var).Tok, m)) || ident.Var is Formal) { // for some reason, formals are not considered to be inherited. - reporter.Error(l.tok, "refinement method cannot assign to variable defined in parent module ('{0}')", ident.Var.Name); + reporter.Error(MessageSource.RefinementTransformer, l.tok, "refinement method cannot assign to variable defined in parent module ('{0}')", ident.Var.Name); } } else if (l is MemberSelectExpr) { var member = ((MemberSelectExpr)l).Member; if (RefinementToken.IsInherited(member.tok, m)) { - reporter.Error(l.tok, "refinement method cannot assign to a field defined in parent module ('{0}')", member.Name); + reporter.Error(MessageSource.RefinementTransformer, l.tok, "refinement method cannot assign to a field defined in parent module ('{0}')", member.Name); } } else { // must be an array element - reporter.Error(l.tok, "new assignments in a refinement method can only assign to state that the module defines (which never includes array elements)"); + reporter.Error(MessageSource.RefinementTransformer, l.tok, "new assignments in a refinement method can only assign to state that the module defines (which never includes array elements)"); } } if (stmt is UpdateStmt) { var s = (UpdateStmt)stmt; foreach (var rhs in s.Rhss) { if (rhs.CanAffectPreviouslyKnownExpressions) { - reporter.Error(rhs.Tok, "assignment RHS in refinement method is not allowed to affect previously defined state"); + reporter.Error(MessageSource.RefinementTransformer, rhs.Tok, "assignment RHS in refinement method is not allowed to affect previously defined state"); } } } diff --git a/Source/Dafny/Reporting.cs b/Source/Dafny/Reporting.cs new file mode 100644 index 00000000..c3797574 --- /dev/null +++ b/Source/Dafny/Reporting.cs @@ -0,0 +1,164 @@ +using Microsoft.Boogie; +using System; +using System.Collections.Generic; +using System.Diagnostics.Contracts; +using System.Linq; +using System.Text; + +namespace Microsoft.Dafny { + public enum ErrorLevel { + Info, Warning, Error + } + + public enum MessageSource { + Parser, Resolver, Translator, Rewriter, Other, + RefinementTransformer, + Cloner + } + + public struct ErrorMessage { + public IToken token; + public string message; + public MessageSource source; + } + + public abstract class ErrorReporter { + public bool ErrorsOnly { get; set; } + public Dictionary> AllMessages { get; private set; } + + protected ErrorReporter() { + ErrorsOnly = false; + AllMessages = new Dictionary>(); + AllMessages[ErrorLevel.Error] = new List(); + AllMessages[ErrorLevel.Warning] = new List(); + AllMessages[ErrorLevel.Info] = new List(); + } + + protected bool ShouldDiscard(MessageSource source, ErrorLevel level) { + return ((ErrorsOnly && level != ErrorLevel.Error) || + (!DafnyOptions.O.PrintTooltips && level == ErrorLevel.Info)); + } + + // This is the only thing that needs to be overriden + public virtual bool Message(MessageSource source, ErrorLevel level, IToken tok, string msg) { + var discard = ShouldDiscard(source, level); + + if (!discard) { + AllMessages[level].Add(new ErrorMessage { token = tok, message = msg }); + return true; + } + + return false; + } + + public int Count(ErrorLevel level) { + return AllMessages[level].Count; + } + + public void Error(MessageSource source, IToken tok, string msg) { + Contract.Requires(tok != null); + Contract.Requires(msg != null); + Message(source, ErrorLevel.Error, tok, msg); + } + + // This method required by the Parser + internal void Error(MessageSource source, string filename, int line, int col, string msg) { + var tok = new Token(line, col); + tok.filename = filename; + Error(source, tok, msg); + } + + public void Error(MessageSource source, IToken tok, string msg, params object[] args) { + Contract.Requires(tok != null); + Contract.Requires(msg != null); + Error(source, tok, String.Format(msg, args)); + } + + public void Error(MessageSource source, Declaration d, string msg, params object[] args) { + Contract.Requires(d != null); + Contract.Requires(msg != null); + Error(source, d.tok, msg, args); + } + + public void Error(MessageSource source, Statement s, string msg, params object[] args) { + Contract.Requires(s != null); + Contract.Requires(msg != null); + Error(source, s.Tok, msg, args); + } + + public void Error(MessageSource source, NonglobalVariable v, string msg, params object[] args) { + Contract.Requires(v != null); + Contract.Requires(msg != null); + Error(source, v.tok, msg, args); + } + + public void Error(MessageSource source, Expression e, string msg, params object[] args) { + Contract.Requires(e != null); + Contract.Requires(msg != null); + Error(source, e.tok, msg, args); + } + + public void Warning(MessageSource source, IToken tok, string msg) { + Contract.Requires(tok != null); + Contract.Requires(msg != null); + Message(source, ErrorLevel.Warning, tok, msg); + } + + public void Warning(MessageSource source, IToken tok, string msg, params object[] args) { + Contract.Requires(tok != null); + Contract.Requires(msg != null); + Warning(source, tok, String.Format(msg, args)); + } + + public void Info(MessageSource source, IToken tok, string msg) { + Contract.Requires(tok != null); + Contract.Requires(msg != null); + Message(source, ErrorLevel.Info, tok, msg); + } + + public void Info(MessageSource source, IToken tok, string msg, params object[] args) { + Contract.Requires(tok != null); + Contract.Requires(msg != null); + Info(source, tok, String.Format(msg, args)); + } + + public string ErrorToString(ErrorLevel header, IToken tok, string msg) { + return ErrorToString_Internal(": " + header.ToString(), tok.filename, tok.line, tok.col, ": " + msg); + } + + public string ErrorToString(ErrorLevel header, string filename, int oneBasedLine, int oneBasedColumn, string msg) { + return ErrorToString_Internal(": " + header.ToString(), filename, oneBasedLine, oneBasedColumn, ": " + msg); + } + + public string ErrorToString_Internal(string header, string filename, int oneBasedLine, int oneBasedColumn, string msg) { + return String.Format("{0}({1},{2}){3}{4}", filename, oneBasedLine, oneBasedColumn - 1, header, msg ?? ""); + } + } + + public class ConsoleErrorReporter : ErrorReporter { + private ConsoleColor ColorForLevel(ErrorLevel level) { + switch (level) { + case ErrorLevel.Error: + return ConsoleColor.Red; + case ErrorLevel.Warning: + return ConsoleColor.Yellow; + case ErrorLevel.Info: + return ConsoleColor.Green; + default: + throw new cce.UnreachableException(); + } + } + + public override bool Message(MessageSource source, ErrorLevel level, IToken tok, string msg) { + if (base.Message(source, level, tok, msg)) { + ConsoleColor previousColor = Console.ForegroundColor; + Console.ForegroundColor = ColorForLevel(level); + Console.WriteLine(ErrorToString(level, tok, msg)); + Console.ForegroundColor = previousColor; + return true; + } else { + return false; + } + } + } +} diff --git a/Source/Dafny/Resolver.cs b/Source/Dafny/Resolver.cs index a58d6e6c..db087109 100644 --- a/Source/Dafny/Resolver.cs +++ b/Source/Dafny/Resolver.cs @@ -12,75 +12,11 @@ using Microsoft.Boogie; namespace Microsoft.Dafny { - public class ResolutionErrorReporter - { - public int ErrorCount = 0; - - /// - /// This method is virtual, because it is overridden in the VSX plug-in for Dafny. - /// - public virtual void Error(IToken tok, string msg, params object[] args) { - Contract.Requires(tok != null); - Contract.Requires(msg != null); - ConsoleColor col = Console.ForegroundColor; - Console.ForegroundColor = ConsoleColor.Red; - Dafny.Util.ReportIssue("Error", tok, msg, args); - Console.ForegroundColor = col; - ErrorCount++; - } - public void Error(Declaration d, string msg, params object[] args) { - Contract.Requires(d != null); - Contract.Requires(msg != null); - Error(d.tok, msg, args); - } - public void Error(Statement s, string msg, params object[] args) { - Contract.Requires(s != null); - Contract.Requires(msg != null); - Error(s.Tok, msg, args); - } - public void Error(NonglobalVariable v, string msg, params object[] args) { - Contract.Requires(v != null); - Contract.Requires(msg != null); - Error(v.tok, msg, args); - } - public void Error(Expression e, string msg, params object[] args) { - Contract.Requires(e != null); - Contract.Requires(msg != null); - Error(e.tok, msg, args); - } - - protected bool reportWarnings = true; - /// - /// Set whether or not to report warnings. Return the state of the previous behavior. - /// - public bool ReportWarnings(bool b) { - var old = reportWarnings; - reportWarnings = b; - return old; - } - public virtual void Warning(IToken tok, string msg, params object[] args) { - Contract.Requires(tok != null); - Contract.Requires(msg != null); - if (reportWarnings) { - ConsoleColor col = Console.ForegroundColor; - Console.ForegroundColor = ConsoleColor.Yellow; - Dafny.Util.ReportIssue("Warning", tok, msg, args); - Console.ForegroundColor = col; - } - } - } - - public struct AdditionalInformation - { - public IToken Token; - public string Text; - public int Length; - } - - public class Resolver : ResolutionErrorReporter + public class Resolver { readonly BuiltIns builtIns; + readonly ErrorReporter reporter; ModuleSignature moduleInfo = null; FreshIdGenerator defaultTempVarIdGenerator; @@ -99,18 +35,6 @@ namespace Microsoft.Dafny return defaultTempVarIdGenerator.FreshId(prefix); } - public Action AdditionalInformationReporter; - - internal void ReportAdditionalInformation(IToken token, string text, int length) - { - Contract.Requires(token != null); - Contract.Requires(text != null); - Contract.Requires(0 <= length); //FIXME: KRML: This should (probably) be the length of the token - if (AdditionalInformationReporter != null) { - AdditionalInformationReporter(new AdditionalInformation { Token = token, Text = text, Length = length }); - } - } - interface IAmbiguousThing { /// @@ -259,13 +183,10 @@ namespace Microsoft.Dafny public Resolver(Program prog) { Contract.Requires(prog != null); builtIns = prog.BuiltIns; + reporter = prog.reporter; // Populate the members of the basic types var trunc = new SpecialField(Token.NoToken, "Trunc", "ToBigInteger()", "", "", false, false, false, Type.Int, null); basicTypeMembers[(int)BasicTypeVariety.Real].Add(trunc.Name, trunc); - - if (DafnyOptions.O.PrintTooltips) { - AdditionalInformationReporter = DefaultInformationReporter; - } } [ContractInvariantMethod] @@ -276,26 +197,22 @@ namespace Microsoft.Dafny Contract.Invariant(cce.NonNullDictionaryAndValues(datatypeCtors) && Contract.ForAll(datatypeCtors.Values, v => cce.NonNullDictionaryAndValues(v))); } - public static void DefaultInformationReporter(AdditionalInformation info) { - Dafny.Util.ReportIssue("Info", info.Token, info.Text); - } - public void ResolveProgram(Program prog) { Contract.Requires(prog != null); - var origErrorCount = ErrorCount; + var origErrorCount = reporter.Count(ErrorLevel.Error); //FIXME (Clement): This is used further below, but not in the >0 comparisons in the next few lines. Is that right? var bindings = new ModuleBindings(null); var b = BindModuleNames(prog.DefaultModuleDef, bindings); bindings.BindName("_module", prog.DefaultModule, b); - if (ErrorCount > 0) { return; } // if there were errors, then the implict ModuleBindings data structure invariant + if (reporter.Count(ErrorLevel.Error) > 0) { return; } // if there were errors, then the implict ModuleBindings data structure invariant // is violated, so Processing dependencies will not succeed. ProcessDependencies(prog.DefaultModule, b, dependencies); // check for cycles in the import graph List cycle = dependencies.TryFindCycle(); if (cycle != null) { var cy = Util.Comma(" -> ", cycle, m => m.Name); - Error(cycle[0], "module definition contains a cycle (note: parent modules implicitly depend on submodules): {0}", cy); + reporter.Error(MessageSource.Resolver, cycle[0], "module definition contains a cycle (note: parent modules implicitly depend on submodules): {0}", cy); } - if (ErrorCount > 0) { return; } // give up on trying to resolve anything else + if (reporter.Count(ErrorLevel.Error) > 0) { return; } // give up on trying to resolve anything else // fill in module heights List sortedDecls = dependencies.TopologicallySortedComponents(); @@ -311,16 +228,16 @@ namespace Microsoft.Dafny } var rewriters = new List(); - var refinementTransformer = new RefinementTransformer(this, AdditionalInformationReporter, prog); + var refinementTransformer = new RefinementTransformer(prog); rewriters.Add(refinementTransformer); - rewriters.Add(new AutoContractsRewriter()); - var opaqueRewriter = new OpaqueFunctionRewriter(this); - rewriters.Add(new AutoReqFunctionRewriter(this, opaqueRewriter)); + rewriters.Add(new AutoContractsRewriter(reporter)); + var opaqueRewriter = new OpaqueFunctionRewriter(this.reporter); + rewriters.Add(new AutoReqFunctionRewriter(this.reporter, opaqueRewriter)); rewriters.Add(opaqueRewriter); - rewriters.Add(new TimeLimitRewriter()); + rewriters.Add(new TimeLimitRewriter(reporter)); if (DafnyOptions.O.AutoTriggers) { - rewriters.Add(new TriggersRewriter(this)); + rewriters.Add(new TriggerGeneratingRewriter(this.reporter)); } systemNameInfo = RegisterTopLevelDecls(prog.BuiltIns.SystemModule, false); @@ -365,7 +282,7 @@ namespace Microsoft.Dafny var literalDecl = (LiteralModuleDecl)decl; var m = literalDecl.ModuleDef; - var errorCount = ErrorCount; + var errorCount = reporter.Count(ErrorLevel.Error); foreach (var r in rewriters) { r.PreResolve(m); } @@ -374,19 +291,20 @@ namespace Microsoft.Dafny literalDecl.Signature.Refines = refinementTransformer.RefinedSig; var sig = literalDecl.Signature; // set up environment - var preResolveErrorCount = ErrorCount; + var preResolveErrorCount = reporter.Count(ErrorLevel.Error); ResolveModuleDefinition(m, sig); foreach (var r in rewriters) { - if (ErrorCount != preResolveErrorCount) { + if (reporter.Count(ErrorLevel.Error) != preResolveErrorCount) { break; } r.PostResolve(m); } - if (ErrorCount == errorCount && !m.IsAbstract) { + if (reporter.Count(ErrorLevel.Error) == errorCount && !m.IsAbstract) { // compilation should only proceed if everything is good, including the signature (which preResolveErrorCount does not include); Contract.Assert(!useCompileSignatures); useCompileSignatures = true; // set Resolver-global flag to indicate that Signatures should be followed to their CompiledSignature - var oldWarnings = ReportWarnings(false); // turn off warning reporting for the clone + var oldErrorsOnly = reporter.ErrorsOnly; + reporter.ErrorsOnly = true; // turn off warning reporting for the clone var nw = new Cloner().CloneModuleDefinition(m, m.CompileName + "_Compile"); var compileSig = RegisterTopLevelDecls(nw, true); compileSig.Refines = refinementTransformer.RefinedSig; @@ -394,13 +312,13 @@ namespace Microsoft.Dafny ResolveModuleDefinition(nw, compileSig); prog.CompileModules.Add(nw); useCompileSignatures = false; // reset the flag - ReportWarnings(oldWarnings); + reporter.ErrorsOnly = oldErrorsOnly; } } else if (decl is AliasModuleDecl) { var alias = (AliasModuleDecl)decl; // resolve the path ModuleSignature p; - if (ResolvePath(alias.Root, alias.Path, out p, this)) { + if (ResolvePath(alias.Root, alias.Path, out p, reporter)) { alias.Signature = p; } else { alias.Signature = new ModuleSignature(); // there was an error, give it a valid but empty signature @@ -408,18 +326,18 @@ namespace Microsoft.Dafny } else if (decl is ModuleFacadeDecl) { var abs = (ModuleFacadeDecl)decl; ModuleSignature p; - if (ResolvePath(abs.Root, abs.Path, out p, this)) { + if (ResolvePath(abs.Root, abs.Path, out p, reporter)) { abs.OriginalSignature = p; // ModuleDefinition.ExclusiveRefinement may not be set at this point but ExclusiveRefinementCount will be. if (0 == abs.Root.Signature.ModuleDef.ExclusiveRefinementCount) { abs.Signature = MakeAbstractSignature(p, abs.FullCompileName, abs.Height, prog.Modules); ModuleSignature compileSig; if (abs.CompilePath != null) { - if (ResolvePath(abs.CompileRoot, abs.CompilePath, out compileSig, this)) { + if (ResolvePath(abs.CompileRoot, abs.CompilePath, out compileSig, reporter)) { if (refinementTransformer.CheckIsRefinement(compileSig, p)) { abs.Signature.CompileSignature = compileSig; } else { - Error( + reporter.Error(MessageSource.Resolver, abs.CompilePath[0], "module " + Util.Comma(".", abs.CompilePath, x => x.val) + " must be a refinement of " + Util.Comma(".", abs.Path, x => x.val)); @@ -437,7 +355,7 @@ namespace Microsoft.Dafny } else { Contract.Assert(false); } Contract.Assert(decl.Signature != null); } - if (ErrorCount != origErrorCount) { + if (reporter.Count(ErrorLevel.Error) != origErrorCount) { // do nothing else return; } @@ -493,7 +411,7 @@ namespace Microsoft.Dafny } foreach (var module in prog.Modules) { foreach (var iter in ModuleDefinition.AllIteratorDecls(module.TopLevelDecls)) { - ReportAdditionalInformation(iter.tok, Printer.IteratorClassToString(iter), iter.Name.Length); + reporter.Info(MessageSource.Resolver, iter.tok, Printer.IteratorClassToString(iter)); } } // fill in other additional information @@ -514,19 +432,19 @@ namespace Microsoft.Dafny // Determine, for each function, whether someone tries to adjust its fuel parameter foreach (var module in prog.Modules) { - CheckForFuelAdjustments(module.tok, module.Attributes, module, this); + CheckForFuelAdjustments(module.tok, module.Attributes, module); foreach (var clbl in ModuleDefinition.AllItersAndCallables(module.TopLevelDecls)) { Statement body = null; if (clbl is Method) { body = ((Method)clbl).Body; - CheckForFuelAdjustments(clbl.Tok,((Method)clbl).Attributes, module, this); + CheckForFuelAdjustments(clbl.Tok,((Method)clbl).Attributes, module); } else if (clbl is IteratorDecl) { body = ((IteratorDecl)clbl).Body; - CheckForFuelAdjustments(clbl.Tok, ((IteratorDecl)clbl).Attributes, module, this); + CheckForFuelAdjustments(clbl.Tok, ((IteratorDecl)clbl).Attributes, module); } if (body != null) { var c = new FuelAdjustment_Visitor(this); - c.Visit(body, new FuelAdjustment_Context(module, this)); + c.Visit(body, new FuelAdjustment_Context(module)); } } } @@ -572,7 +490,7 @@ namespace Microsoft.Dafny } // Note, in the following line, we use the location information for "clbl", not "m". These // are the same, except in the case where "clbl" is a CoLemma and "m" is a prefix lemma. - ReportAdditionalInformation(clbl.Tok, s, clbl.Tok.val.Length); + reporter.Info(MessageSource.Resolver, clbl.Tok, s); } } } @@ -595,7 +513,7 @@ namespace Microsoft.Dafny var decr = clbl.Decreases.Expressions; if (DafnyOptions.O.Dafnycc) { if (decr.Count > 1) { - Error(decr[1].tok, "In dafnycc mode, only one decreases expression is allowed"); + reporter.Error(MessageSource.Resolver, decr[1].tok, "In dafnycc mode, only one decreases expression is allowed"); } // In dafnycc mode, only consider first argument if (decr.Count == 0 && clbl.Ins.Count > 0) { @@ -757,11 +675,11 @@ namespace Microsoft.Dafny // resolve var datatypeDependencies = new Graph(); var codatatypeDependencies = new Graph(); - int prevErrorCount = ErrorCount; + int prevErrorCount = reporter.Count(ErrorLevel.Error); ResolveTopLevelDecls_Signatures(m, m.TopLevelDecls, datatypeDependencies, codatatypeDependencies); ResolveAttributes(m.Attributes, new ResolveOpts(new NoContext(m.Module), false)); // Must follow ResolveTopLevelDecls_Signatures, in case attributes refer to members - if (ErrorCount == prevErrorCount) { - ResolveTopLevelDecls_Meat(m.TopLevelDecls, datatypeDependencies, codatatypeDependencies); + if (reporter.Count(ErrorLevel.Error) == prevErrorCount) { + ResolveTopLevelDecls_Core(m.TopLevelDecls, datatypeDependencies, codatatypeDependencies); } } @@ -819,17 +737,17 @@ namespace Microsoft.Dafny var subdecl = (LiteralModuleDecl)tld; var subBindings = BindModuleNames(subdecl.ModuleDef, bindings); if (!bindings.BindName(subdecl.Name, subdecl, subBindings)) { - Error(subdecl.tok, "Duplicate module name: {0}", subdecl.Name); + reporter.Error(MessageSource.Resolver, subdecl.tok, "Duplicate module name: {0}", subdecl.Name); } } else if (tld is ModuleFacadeDecl) { var subdecl = (ModuleFacadeDecl)tld; if (!bindings.BindName(subdecl.Name, subdecl, null)) { - Error(subdecl.tok, "Duplicate module name: {0}", subdecl.Name); + reporter.Error(MessageSource.Resolver, subdecl.tok, "Duplicate module name: {0}", subdecl.Name); } } else if (tld is AliasModuleDecl) { var subdecl = (AliasModuleDecl)tld; if (!bindings.BindName(subdecl.Name, subdecl, null)) { - Error(subdecl.tok, "Duplicate module name: {0}", subdecl.Name); + reporter.Error(MessageSource.Resolver, subdecl.tok, "Duplicate module name: {0}", subdecl.Name); } } } @@ -840,9 +758,9 @@ namespace Microsoft.Dafny if (m.RefinementBaseName != null) { ModuleDecl other; if (!bindings.TryLookup(m.RefinementBaseName[0], out other)) { - Error(m.RefinementBaseName[0], "module {0} named as refinement base does not exist", m.RefinementBaseName[0].val); + reporter.Error(MessageSource.Resolver, m.RefinementBaseName[0], "module {0} named as refinement base does not exist", m.RefinementBaseName[0].val); } else if (other is LiteralModuleDecl && ((LiteralModuleDecl)other).ModuleDef == m) { - Error(m.RefinementBaseName[0], "module cannot refine itself: {0}", m.RefinementBaseName[0].val); + reporter.Error(MessageSource.Resolver, m.RefinementBaseName[0], "module cannot refine itself: {0}", m.RefinementBaseName[0].val); } else { Contract.Assert(other != null); // follows from postcondition of TryGetValue dependencies.AddEdge(decl, other); @@ -866,7 +784,7 @@ namespace Microsoft.Dafny var alias = moduleDecl as AliasModuleDecl; ModuleDecl root; if (!bindings.TryLookupIgnore(alias.Path[0], out root, alias)) - Error(alias.tok, ModuleNotFoundErrorMessage(0, alias.Path)); + reporter.Error(MessageSource.Resolver, alias.tok, ModuleNotFoundErrorMessage(0, alias.Path)); else { dependencies.AddEdge(moduleDecl, root); alias.Root = root; @@ -875,14 +793,14 @@ namespace Microsoft.Dafny var abs = moduleDecl as ModuleFacadeDecl; ModuleDecl root; if (!bindings.TryLookup(abs.Path[0], out root)) - Error(abs.tok, ModuleNotFoundErrorMessage(0, abs.Path)); + reporter.Error(MessageSource.Resolver, abs.tok, ModuleNotFoundErrorMessage(0, abs.Path)); else { dependencies.AddEdge(moduleDecl, root); abs.Root = root; } if (abs.CompilePath != null) { if (!bindings.TryLookup(abs.CompilePath[0], out root)) - Error(abs.tok, ModuleNotFoundErrorMessage(0, abs.CompilePath)); + reporter.Error(MessageSource.Resolver, abs.tok, ModuleNotFoundErrorMessage(0, abs.CompilePath)); else { dependencies.AddEdge(moduleDecl, root); abs.CompileRoot = root; @@ -990,7 +908,7 @@ namespace Microsoft.Dafny Contract.Assert(d != null); // register the class/datatype/module name if (toplevels.ContainsKey(d.Name)) { - Error(d, "Duplicate name of top-level declaration: {0}", d.Name); + reporter.Error(MessageSource.Resolver, d, "Duplicate name of top-level declaration: {0}", d.Name); } else { toplevels[d.Name] = d; sig.TopLevels[d.Name] = d; @@ -1014,7 +932,7 @@ namespace Microsoft.Dafny // First, register the iterator's in- and out-parameters as readonly fields foreach (var p in iter.Ins) { if (members.ContainsKey(p.Name)) { - Error(p, "Name of in-parameter is used by another member of the iterator: {0}", p.Name); + reporter.Error(MessageSource.Resolver, p, "Name of in-parameter is used by another member of the iterator: {0}", p.Name); } else { var field = new SpecialField(p.tok, p.Name, p.CompileName, "", "", p.IsGhost, false, false, p.Type, null); field.EnclosingClass = iter; // resolve here @@ -1024,7 +942,7 @@ namespace Microsoft.Dafny } foreach (var p in iter.Outs) { if (members.ContainsKey(p.Name)) { - Error(p, "Name of yield-parameter is used by another member of the iterator: {0}", p.Name); + reporter.Error(MessageSource.Resolver, p, "Name of yield-parameter is used by another member of the iterator: {0}", p.Name); } else { var field = new SpecialField(p.tok, p.Name, p.CompileName, "", "", p.IsGhost, true, true, p.Type, null); field.EnclosingClass = iter; // resolve here @@ -1036,7 +954,7 @@ namespace Microsoft.Dafny foreach (var p in iter.Outs) { var nm = p.Name + "s"; if (members.ContainsKey(nm)) { - Error(p.tok, "Name of implicit yield-history variable '{0}' is already used by another member of the iterator", p.Name); + reporter.Error(MessageSource.Resolver, p.tok, "Name of implicit yield-history variable '{0}' is already used by another member of the iterator", p.Name); } else { var tp = new SeqType(p.Type.IsSubrangeType ? new IntType() : p.Type); var field = new SpecialField(p.tok, nm, nm, "", "", true, true, false, tp, null); @@ -1108,7 +1026,7 @@ namespace Microsoft.Dafny iter.Member_MoveNext = moveNext; MemberDecl member; if (members.TryGetValue(init.Name, out member)) { - Error(member.tok, "member name '{0}' is already predefined for this iterator", init.Name); + reporter.Error(MessageSource.Resolver, member.tok, "member name '{0}' is already predefined for this iterator", init.Name); } else { members.Add(init.Name, init); iter.Members.Add(init); @@ -1116,13 +1034,13 @@ namespace Microsoft.Dafny // If the name of the iterator is "Valid" or "MoveNext", one of the following will produce an error message. That // error message may not be as clear as it could be, but the situation also seems unlikely to ever occur in practice. if (members.TryGetValue("Valid", out member)) { - Error(member.tok, "member name 'Valid' is already predefined for iterators"); + reporter.Error(MessageSource.Resolver, member.tok, "member name 'Valid' is already predefined for iterators"); } else { members.Add(valid.Name, valid); iter.Members.Add(valid); } if (members.TryGetValue("MoveNext", out member)) { - Error(member.tok, "member name 'MoveNext' is already predefined for iterators"); + reporter.Error(MessageSource.Resolver, member.tok, "member name 'MoveNext' is already predefined for iterators"); } else { members.Add(moveNext.Name, moveNext); iter.Members.Add(moveNext); @@ -1140,7 +1058,7 @@ namespace Microsoft.Dafny members.Add(m.Name, m); if (m is Constructor) { if (cl is TraitDecl) { - Error(m.tok, "a trait is not allowed to declare a constructor"); + reporter.Error(MessageSource.Resolver, m.tok, "a trait is not allowed to declare a constructor"); } else { cl.HasConstructor = true; } @@ -1196,9 +1114,9 @@ namespace Microsoft.Dafny members.Add(extraName, extraMember); } } else if (m is Constructor && !((Constructor)m).HasName) { - Error(m, "More than one anonymous constructor"); + reporter.Error(MessageSource.Resolver, m, "More than one anonymous constructor"); } else { - Error(m, "Duplicate member name: {0}", m.Name); + reporter.Error(MessageSource.Resolver, m, "Duplicate member name: {0}", m.Name); } } if (cl.IsDefaultClass) { @@ -1222,9 +1140,9 @@ namespace Microsoft.Dafny foreach (DatatypeCtor ctor in dt.Ctors) { if (ctor.Name.EndsWith("?")) { - Error(ctor, "a datatype constructor name is not allowed to end with '?'"); + reporter.Error(MessageSource.Resolver, ctor, "a datatype constructor name is not allowed to end with '?'"); } else if (ctors.ContainsKey(ctor.Name)) { - Error(ctor, "Duplicate datatype constructor name: {0}", ctor.Name); + reporter.Error(MessageSource.Resolver, ctor, "Duplicate datatype constructor name: {0}", ctor.Name); } else { ctors.Add(ctor.Name, ctor); @@ -1251,7 +1169,7 @@ namespace Microsoft.Dafny foreach (var formal in ctor.Formals) { bool nameError = false; if (formal.HasName && members.ContainsKey(formal.Name)) { - Error(ctor, "Name of deconstructor is used by another member of the datatype: {0}", formal.Name); + reporter.Error(MessageSource.Resolver, ctor, "Name of deconstructor is used by another member of the datatype: {0}", formal.Name); nameError = true; } var dtor = new DatatypeDestructor(formal.tok, ctor, formal, formal.Name, "dtor_" + formal.CompileName, "", "", formal.IsGhost, formal.Type, null); @@ -1301,8 +1219,7 @@ namespace Microsoft.Dafny } - public static bool ResolvePath(ModuleDecl root, List Path, out ModuleSignature p, ResolutionErrorReporter reporter) { - Contract.Requires(reporter != null); + public static bool ResolvePath(ModuleDecl root, List Path, out ModuleSignature p, ErrorReporter reporter) { p = root.Signature; int i = 1; while (i < Path.Count) { @@ -1311,7 +1228,7 @@ namespace Microsoft.Dafny p = pp; i++; } else { - reporter.Error(Path[i], ModuleNotFoundErrorMessage(i, Path)); + reporter.Error(MessageSource.Resolver, Path[i], ModuleNotFoundErrorMessage(i, Path)); break; } } @@ -1366,7 +1283,7 @@ namespace Microsoft.Dafny { if (!(def.IsDefaultModule)) // _module is allowed to contain abstract modules, but not be abstract itself. Note this presents a challenge to // trusted verification, as toplevels can't be trusted if they invoke abstract module members. - Error(d.tok, "an abstract module can only be imported into other abstract modules, not a concrete one."); + reporter.Error(MessageSource.Resolver, d.tok, "an abstract module can only be imported into other abstract modules, not a concrete one."); } else { // physical modules are allowed everywhere } @@ -1392,7 +1309,7 @@ namespace Microsoft.Dafny if (cycle != null) { Contract.Assert(cycle.Count != 0); var erste = cycle[0]; - Error(erste.Tok, "Cycle among redirecting types (newtypes, type synonyms): {0} -> {1}", Util.Comma(" -> ", cycle, syn => syn.Name), erste.Name); + reporter.Error(MessageSource.Resolver, erste.Tok, "Cycle among redirecting types (newtypes, type synonyms): {0} -> {1}", Util.Comma(" -> ", cycle, syn => syn.Name), erste.Name); } } @@ -1416,14 +1333,14 @@ namespace Microsoft.Dafny new NativeType("long", Int64.MinValue, 0x8000000000000000, "L", false), }; - public void ResolveTopLevelDecls_Meat(List/*!*/ declarations, Graph/*!*/ datatypeDependencies, Graph/*!*/ codatatypeDependencies) { + public void ResolveTopLevelDecls_Core(List/*!*/ declarations, Graph/*!*/ datatypeDependencies, Graph/*!*/ codatatypeDependencies) { Contract.Requires(declarations != null); Contract.Requires(cce.NonNullElements(datatypeDependencies)); Contract.Requires(cce.NonNullElements(codatatypeDependencies)); Contract.Requires(NFBC_Count == 0); Contract.Ensures(NFBC_Count == 0); - int prevErrorCount = ErrorCount; + int prevErrorCount = reporter.Count(ErrorLevel.Error); // Resolve the meat of classes and iterators, the definitions of type synonyms, and the type parameters of all top-level type declarations // First, resolve the newtype declarations and the constraint clauses, including filling in .ResolvedOp fields. This is needed for the @@ -1438,7 +1355,7 @@ namespace Microsoft.Dafny ResolveAttributes(d.Attributes, new ResolveOpts(new NoContext(d.Module), false)); // this check can be done only after it has been determined that the redirected types do not involve cycles if (!dd.BaseType.IsNumericBased()) { - Error(dd.tok, "newtypes must be based on some numeric type (got {0})", dd.BaseType); + reporter.Error(MessageSource.Resolver, dd.tok, "newtypes must be based on some numeric type (got {0})", dd.BaseType); } // type check the constraint, if any if (dd.Var != null) { @@ -1451,10 +1368,10 @@ namespace Microsoft.Dafny ResolveExpression(dd.Constraint, new ResolveOpts(dd, false, true)); Contract.Assert(dd.Constraint.Type != null); // follows from postcondition of ResolveExpression if (!UnifyTypes(dd.Constraint.Type, Type.Bool)) { - Error(dd.Constraint, "newtype constraint must be of type bool (instead got {0})", dd.Constraint.Type); + reporter.Error(MessageSource.Resolver, dd.Constraint, "newtype constraint must be of type bool (instead got {0})", dd.Constraint.Type); } if (!CheckTypeInference_Visitor.IsDetermined(dd.BaseType.NormalizeExpand())) { - Error(dd.tok, "newtype's base type is not fully determined; add an explicit type for '{0}'", dd.Var.Name); + reporter.Error(MessageSource.Resolver, dd.tok, "newtype's base type is not fully determined; add an explicit type for '{0}'", dd.Var.Name); } CheckTypeInference(dd.Constraint); scope.PopMarker(); @@ -1464,7 +1381,7 @@ namespace Microsoft.Dafny // Now, we're ready for the other declarations. foreach (TopLevelDecl d in declarations) { if (d is TraitDecl && d.TypeArgs.Count > 0) { - Error(d, "sorry, traits with type parameters are not supported"); + reporter.Error(MessageSource.Resolver, d, "sorry, traits with type parameters are not supported"); } allTypeParameters.PushMarker(); ResolveTypeParameters(d.TypeArgs, false, d); @@ -1483,15 +1400,15 @@ namespace Microsoft.Dafny allTypeParameters.PopMarker(); } - if (ErrorCount == prevErrorCount) { + if (reporter.Count(ErrorLevel.Error) == prevErrorCount) { foreach (var e in needFiniteBoundsChecks_SetComprehension) { var missingBounds = new List(); CheckTypeInference(e.Range); // we need to resolve operators before the call to DiscoverBounds - e.Bounds = DiscoverBounds(e.tok, e.BoundVars, e.Range, true, false, missingBounds); + e.Bounds = DiscoverBounds(e.tok, e.BoundVars, e.Range, true, false, missingBounds, reporter); if (missingBounds.Count != 0) { e.MissingBounds = missingBounds; foreach (var bv in e.MissingBounds) { - Error(e, "a set comprehension must produce a finite set, but Dafny's heuristics can't figure out how to produce a bounded set of values for '{0}'", bv.Name); + reporter.Error(MessageSource.Resolver, e, "a set comprehension must produce a finite set, but Dafny's heuristics can't figure out how to produce a bounded set of values for '{0}'", bv.Name); } } } @@ -1501,11 +1418,11 @@ namespace Microsoft.Dafny var constraint = e.RHSs[0]; var missingBounds = new List(); CheckTypeInference(constraint); // we need to resolve operators before the call to DiscoverBounds - var allBounds = DiscoverBoundsAux(e.tok, new List(e.BoundVars), constraint, true, true, true, missingBounds); + var allBounds = DiscoverBoundsAux(e.tok, new List(e.BoundVars), constraint, true, true, true, missingBounds, reporter); if (missingBounds.Count != 0) { e.Constraint_MissingBounds = missingBounds; foreach (var bv in e.Constraint_MissingBounds) { - Error(e, "a non-ghost let-such-that constraint must be compilable, but Dafny's heuristics can't figure out how to produce a bounded set of values for '{0}'", bv.Name); + reporter.Error(MessageSource.Resolver, e, "a non-ghost let-such-that constraint must be compilable, but Dafny's heuristics can't figure out how to produce a bounded set of values for '{0}'", bv.Name); } } else { e.Constraint_Bounds = new List(); @@ -1525,7 +1442,7 @@ namespace Microsoft.Dafny nativeTypeMap.Add(nativeType.Name, nativeType); } - if (ErrorCount == prevErrorCount) { + if (reporter.Count(ErrorLevel.Error) == prevErrorCount) { // Check that type inference went well everywhere; this will also fill in the .ResolvedOp field in binary expressions foreach (TopLevelDecl d in declarations) { if (d is IteratorDecl) { @@ -1547,7 +1464,7 @@ namespace Microsoft.Dafny Attributes.MatchingValueOption.Empty, Attributes.MatchingValueOption.Bool, Attributes.MatchingValueOption.String }, - err => Error(dd, err)); + err => reporter.Error(MessageSource.Resolver, dd, err)); if (hasNativeTypeAttr) { if (nativeTypeAttr is bool) { boolNativeType = (bool)nativeTypeAttr; @@ -1556,16 +1473,16 @@ namespace Microsoft.Dafny if (nativeTypeMap.ContainsKey(keyString)) { stringNativeType = nativeTypeMap[keyString]; } else { - Error(dd, "Unsupported nativeType {0}", keyString); + reporter.Error(MessageSource.Resolver, dd, "Unsupported nativeType {0}", keyString); } } } if (stringNativeType != null || boolNativeType == true) { if (!dd.BaseType.IsNumericBased(Type.NumericPersuation.Int)) { - Error(dd, "nativeType can only be used on integral types"); + reporter.Error(MessageSource.Resolver, dd, "nativeType can only be used on integral types"); } if (dd.Var == null) { - Error(dd, "nativeType can only be used if newtype specifies a constraint"); + reporter.Error(MessageSource.Resolver, dd, "nativeType can only be used if newtype specifies a constraint"); } } if (dd.Var != null) { @@ -1588,7 +1505,7 @@ namespace Microsoft.Dafny }; var missingBounds = new List(); var bounds = DiscoverBounds(dd.Constraint.tok, new List { dd.Var }, dd.Constraint, - true, true, missingBounds); + true, true, missingBounds, reporter); List potentialNativeTypes = (stringNativeType != null) ? new List { stringNativeType } : (boolNativeType == false) ? new List() : @@ -1621,18 +1538,18 @@ namespace Microsoft.Dafny } } if (dd.NativeType == null && (boolNativeType == true || stringNativeType != null)) { - Error(dd, "Dafny's heuristics cannot find a compatible native type. " + + reporter.Error(MessageSource.Resolver, dd, "Dafny's heuristics cannot find a compatible native type. " + "Hint: try writing a newtype constraint of the form 'i:int | lowerBound <= i < upperBound && (...any additional constraints...)'"); } if (dd.NativeType != null && stringNativeType == null) { - ReportAdditionalInformation(dd.tok, "{:nativeType \"" + dd.NativeType.Name + "\"}", dd.tok.val.Length); + reporter.Info(MessageSource.Resolver, dd.tok, "{:nativeType \"" + dd.NativeType.Name + "\"}"); } } } } } - if (ErrorCount == prevErrorCount) { + if (reporter.Count(ErrorLevel.Error) == prevErrorCount) { // fill in the postconditions and bodies of prefix lemmas foreach (var com in ModuleDefinition.AllFixpointLemmas(declarations)) { var prefixLemma = com.PrefixLemma; @@ -1646,7 +1563,7 @@ namespace Microsoft.Dafny foreach (var p in com.Ens) { var coConclusions = new HashSet(); CollectFriendlyCallsInFixpointLemmaSpecification(p.E, true, coConclusions, true); - var subst = new FixpointLemmaSpecificationSubstituter(coConclusions, new IdentifierExpr(k.tok, k.Name), this, true); + var subst = new FixpointLemmaSpecificationSubstituter(coConclusions, new IdentifierExpr(k.tok, k.Name), this.reporter, true); var post = subst.CloneExpr(p.E); prefixLemma.Ens.Add(new MaybeFreeExpression(post, p.IsFree)); } @@ -1656,7 +1573,7 @@ namespace Microsoft.Dafny foreach (var p in com.Req) { var antecedents = new HashSet(); CollectFriendlyCallsInFixpointLemmaSpecification(p.E, true, antecedents, false); - var subst = new FixpointLemmaSpecificationSubstituter(antecedents, new IdentifierExpr(k.tok, k.Name), this, false); + var subst = new FixpointLemmaSpecificationSubstituter(antecedents, new IdentifierExpr(k.tok, k.Name), this.reporter, false); var pre = subst.CloneExpr(p.E); prefixLemma.Req.Add(new MaybeFreeExpression(pre, p.IsFree)); } @@ -1665,7 +1582,7 @@ namespace Microsoft.Dafny Contract.Assume(prefixLemma.Body == null); // this is not supposed to have been filled in before if (com.Body != null) { var kMinusOne = new BinaryExpr(com.tok, BinaryExpr.Opcode.Sub, new IdentifierExpr(k.tok, k.Name), new LiteralExpr(com.tok, 1)); - var subst = new FixpointLemmaBodyCloner(com, kMinusOne, this); + var subst = new FixpointLemmaBodyCloner(com, kMinusOne, this.reporter); var mainBody = subst.CloneBlockStmt(com.Body); var kPositive = new BinaryExpr(com.tok, BinaryExpr.Opcode.Lt, new LiteralExpr(com.tok, 0), new IdentifierExpr(k.tok, k.Name)); var condBody = new IfStmt(com.BodyStartTok, mainBody.EndTok, kPositive, mainBody, null); @@ -1699,7 +1616,7 @@ namespace Microsoft.Dafny } } - if (ErrorCount == prevErrorCount) { // because CheckCoCalls requires the given expression to have been successfully resolved + if (reporter.Count(ErrorLevel.Error) == prevErrorCount) { // because CheckCoCalls requires the given expression to have been successfully resolved // Perform the guardedness check on co-datatypes foreach (var repr in ModuleDefinition.AllFunctionSCCs(declarations)) { var module = repr.EnclosingModule; @@ -1734,7 +1651,7 @@ namespace Microsoft.Dafny foreach (var c in coCandidates) { c.CandidateCall.CoCall = FunctionCallExpr.CoCallResolution.Yes; c.EnclosingCoConstructor.IsCoCall = true; - ReportAdditionalInformation(c.CandidateCall.tok, "co-recursive call", c.CandidateCall.Name.Length); + reporter.Info(MessageSource.Resolver, c.CandidateCall.tok, "co-recursive call"); } // Finally, fill in the CoClusterTarget field // Start by setting all the CoClusterTarget fields to CoRecursiveTargetAllTheWay. @@ -1929,11 +1846,11 @@ namespace Microsoft.Dafny // Check here for the presence of any 'ensures' clauses, which are not allowed (because we're not sure // of their soundness) if (fn.Ens.Count != 0) { - Error(fn.Ens[0].tok, "a {0} is not allowed to declare any ensures clause", member.WhatKind); + reporter.Error(MessageSource.Resolver, fn.Ens[0].tok, "a {0} is not allowed to declare any ensures clause", member.WhatKind); } // Also check for 'reads' clauses if (fn.Reads.Count != 0) { - Error(fn.Reads[0].tok, "a {0} is not allowed to declare any reads clause", member.WhatKind); // (why?) + reporter.Error(MessageSource.Resolver, fn.Reads[0].tok, "a {0} is not allowed to declare any reads clause", member.WhatKind); // (why?) } if (fn.Body != null) { FixpointPredicateChecks(fn.Body, fn, CallingPosition.Positive); @@ -1949,7 +1866,7 @@ namespace Microsoft.Dafny var dd = (NewtypeDecl)d; if (dd.Module.CallGraph.GetSCCSize(dd) != 1) { var cycle = Util.Comma(" -> ", dd.Module.CallGraph.GetSCC(dd), clbl => clbl.NameRelativeToModule); - Error(dd.tok, "recursive dependency involving a newtype: " + cycle); + reporter.Error(MessageSource.Resolver, dd.tok, "recursive dependency involving a newtype: " + cycle); } } } @@ -1967,45 +1884,14 @@ namespace Microsoft.Dafny Contract.Requires(resolver != null); this.resolver = resolver; } - public void Error(IToken tok, string msg, params object[] args) { - Contract.Requires(tok != null); - Contract.Requires(msg != null); - Contract.Requires(args != null); - resolver.Error(tok, msg, args); - } - public void Error(Expression expr, string msg, params object[] args) { - Contract.Requires(expr != null); - Contract.Requires(msg != null); - Contract.Requires(args != null); - Error(expr.tok, msg, args); - } } abstract class ResolverTopDownVisitor : TopDownVisitor { - Resolver resolver; + protected Resolver resolver; public ResolverTopDownVisitor(Resolver resolver) { Contract.Requires(resolver != null); this.resolver = resolver; } - protected void Error(IToken tok, string msg, params object[] args) - { - Contract.Requires(tok != null); - Contract.Requires(msg != null); - Contract.Requires(args != null); - resolver.Error(tok, msg, args); - } - protected void Error(Expression expr, string msg, params object[] args) - { - Contract.Requires(expr != null); - Contract.Requires(msg != null); - Contract.Requires(args != null); - Error(expr.tok, msg, args); - } - protected void ReportAdditionalInformation(IToken tok, string text, int length) - { - Contract.Requires(tok != null); - resolver.ReportAdditionalInformation(tok, text, length); - } } #endregion Visitors @@ -2027,12 +1913,12 @@ namespace Microsoft.Dafny if (hasTailRecursionPreference && !tail) { // the user specifically requested no tail recursion, so do nothing else } else if (hasTailRecursionPreference && tail && m.IsGhost) { - Error(m.tok, "tail recursion can be specified only for methods that will be compiled, not for ghost methods"); + reporter.Error(MessageSource.Resolver, m.tok, "tail recursion can be specified only for methods that will be compiled, not for ghost methods"); } else { var module = m.EnclosingClass.Module; var sccSize = module.CallGraph.GetSCCSize(m); if (hasTailRecursionPreference && 2 <= sccSize) { - Error(m.tok, "sorry, tail-call optimizations are not supported for mutually recursive methods"); + reporter.Error(MessageSource.Resolver, m.tok, "sorry, tail-call optimizations are not supported for mutually recursive methods"); } else if (hasTailRecursionPreference || sccSize == 1) { CallStmt tailCall = null; var status = CheckTailRecursive(m.Body.Body, m, ref tailCall, hasTailRecursionPreference); @@ -2040,7 +1926,7 @@ namespace Microsoft.Dafny m.IsTailRecursive = true; if (tailCall != null) { // this means there was at least one recursive call - ReportAdditionalInformation(m.tok, "tail recursive", m.Name.Length); + reporter.Info(MessageSource.Resolver, m.tok, "tail recursive"); } } } @@ -2048,7 +1934,7 @@ namespace Microsoft.Dafny } } else if (member is Function) { var f = (Function)member; - var errorCount = ErrorCount; + var errorCount = reporter.Count(ErrorLevel.Error); f.Req.Iter(CheckTypeInference); f.Ens.Iter(CheckTypeInference); f.Reads.Iter(fe => CheckTypeInference(fe.E)); @@ -2057,10 +1943,10 @@ namespace Microsoft.Dafny CheckTypeInference(f.Body); bool tail = true; if (Attributes.ContainsBool(f.Attributes, "tailrecursion", ref tail) && tail) { - Error(f.tok, "sorry, tail-call functions are not supported"); + reporter.Error(MessageSource.Resolver, f.tok, "sorry, tail-call functions are not supported"); } } - if (errorCount == ErrorCount && f is FixpointPredicate) { + if (errorCount == reporter.Count(ErrorLevel.Error) && f is FixpointPredicate) { var cop = (FixpointPredicate)f; CheckTypeInference_Member(cop.PrefixPredicate); } @@ -2120,7 +2006,7 @@ namespace Microsoft.Dafny if (e != null) { foreach (var bv in e.BoundVars) { if (!IsDetermined(bv.Type.Normalize())) { - Error(bv.tok, "type of bound variable '{0}' could not be determined; please specify the type explicitly", + resolver.reporter.Error(MessageSource.Resolver, bv.tok, "type of bound variable '{0}' could not be determined; please specify the type explicitly", bv.Name); } } @@ -2130,7 +2016,7 @@ namespace Microsoft.Dafny if (e.Member is Function || e.Member is Method) { foreach (var p in e.TypeApplication) { if (!IsDetermined(p.Normalize())) { - Error(e.tok, "type '{0}' to the {2} '{1}' is not determined", p, e.Member.Name, e.Member.WhatKind); + resolver.reporter.Error(MessageSource.Resolver, e.tok, "type '{0}' to the {2} '{1}' is not determined", p, e.Member.Name, e.Member.WhatKind); } } } @@ -2138,7 +2024,7 @@ namespace Microsoft.Dafny var e = (FunctionCallExpr)expr; foreach (var p in e.TypeArgumentSubstitutions) { if (!IsDetermined(p.Value.Normalize())) { - Error(e.tok, "type variable '{0}' in the function call to '{1}' could not be determined{2}", p.Key.Name, e.Name, + resolver.reporter.Error(MessageSource.Resolver, e.tok, "type variable '{0}' in the function call to '{1}' could not be determined{2}", p.Key.Name, e.Name, (e.Name.Contains("reveal_") || e.Name.Contains("_FULL")) //CLEMENT should this be StartsWith and EndsWith? ? ". If you are making an opaque function, make sure that the function can be called." : "" @@ -2150,7 +2036,7 @@ namespace Microsoft.Dafny foreach (var p in e.LHSs) { foreach (var x in p.Vars) { if (!IsDetermined(x.Type.Normalize())) { - Error(e.tok, "the type of the bound variable '{0}' could not be determined", x.Name); + resolver.reporter.Error(MessageSource.Resolver, e.tok, "the type of the bound variable '{0}' could not be determined", x.Name); } } } @@ -2218,7 +2104,7 @@ namespace Microsoft.Dafny var proxy = (TypeProxy)t; if (!UnderspecifiedTypeProxies.Contains(proxy)) { // report an error for this TypeProxy only once - Error(tok, "the type of this {0} is underspecified", what); + resolver.reporter.Error(MessageSource.Resolver, tok, "the type of this {0} is underspecified", what); UnderspecifiedTypeProxies.Add(proxy); } return false; @@ -2274,7 +2160,7 @@ namespace Microsoft.Dafny if (status == TailRecursionStatus.TailCallSpent) { // a tail call cannot be followed by non-ghost code if (reportErrors) { - Error(tailCall.Tok, "this recursive call is not recognized as being tail recursive, because it is followed by non-ghost code"); + reporter.Error(MessageSource.Resolver, tailCall.Tok, "this recursive call is not recognized as being tail recursive, because it is followed by non-ghost code"); } return TailRecursionStatus.NotTailRecursive; } @@ -2322,7 +2208,7 @@ namespace Microsoft.Dafny // all is good } else { if (reportErrors) { - Error(s.Tok, "the recursive call to '{0}' is not tail recursive because the actual out-parameter {1} is not the formal out-parameter '{2}'", s.Method.Name, i, formal.Name); + reporter.Error(MessageSource.Resolver, s.Tok, "the recursive call to '{0}' is not tail recursive because the actual out-parameter {1} is not the formal out-parameter '{2}'", s.Method.Name, i, formal.Name); } return TailRecursionStatus.NotTailRecursive; } @@ -2368,7 +2254,7 @@ namespace Microsoft.Dafny if (status == TailRecursionStatus.NotTailRecursive) { // an error has already been reported } else if (reportErrors) { - Error(tailCall.Tok, "a recursive call inside a loop is not recognized as being a tail call"); + reporter.Error(MessageSource.Resolver, tailCall.Tok, "a recursive call inside a loop is not recognized as being a tail call"); } return TailRecursionStatus.NotTailRecursive; } @@ -2380,7 +2266,7 @@ namespace Microsoft.Dafny if (status == TailRecursionStatus.NotTailRecursive) { // an error has already been reported } else if (reportErrors) { - Error(tailCall.Tok, "a recursive call inside a loop is not recognized as being a tail call"); + reporter.Error(MessageSource.Resolver, tailCall.Tok, "a recursive call inside a loop is not recognized as being a tail call"); } return TailRecursionStatus.NotTailRecursive; } @@ -2395,7 +2281,7 @@ namespace Microsoft.Dafny if (status == TailRecursionStatus.NotTailRecursive) { // an error has already been reported } else if (reportErrors) { - Error(tailCall.Tok, "a recursive call inside a forall statement is not a tail call"); + reporter.Error(MessageSource.Resolver, tailCall.Tok, "a recursive call inside a forall statement is not a tail call"); } return TailRecursionStatus.NotTailRecursive; } @@ -2432,7 +2318,7 @@ namespace Microsoft.Dafny // ------------------------------------------------------------------------------------------------------ #region FuelAdjustmentChecks - protected static void CheckForFuelAdjustments(IToken tok, Attributes attrs, ModuleDefinition currentModule, ResolutionErrorReporter reporter) { + protected void CheckForFuelAdjustments(IToken tok, Attributes attrs, ModuleDefinition currentModule) { List> results = Attributes.FindAllExpressions(attrs, "fuel"); if (results != null) { @@ -2445,7 +2331,7 @@ namespace Microsoft.Dafny if (f != null) { f.IsFueled = true; if (f.IsProtected && currentModule != f.EnclosingClass.Module) { - reporter.Error(tok, "cannot adjust fuel for protected function {0} from another module", f.Name); + reporter.Error(MessageSource.Resolver, tok, "cannot adjust fuel for protected function {0} from another module", f.Name); } } } @@ -2457,10 +2343,8 @@ namespace Microsoft.Dafny public class FuelAdjustment_Context { public ModuleDefinition currentModule; - public ResolutionErrorReporter reporter; - public FuelAdjustment_Context(ModuleDefinition currentModule, ResolutionErrorReporter reporter) { + public FuelAdjustment_Context(ModuleDefinition currentModule) { this.currentModule = currentModule; - this.reporter = reporter; } } @@ -2472,7 +2356,7 @@ namespace Microsoft.Dafny } protected override bool VisitOneStmt(Statement stmt, ref FuelAdjustment_Context st) { - Resolver.CheckForFuelAdjustments(stmt.Tok, stmt.Attributes, st.currentModule, st.reporter); + resolver.CheckForFuelAdjustments(stmt.Tok, stmt.Attributes, st.currentModule); return true; } } @@ -2594,7 +2478,7 @@ namespace Microsoft.Dafny var article = context is InductivePredicate ? "an" : "a"; // we're looking at a recursive call if (!(context is InductivePredicate ? e.Function is InductivePredicate : e.Function is CoPredicate)) { - Error(e, "a recursive call from {0} {1} can go only to other {1}s", article, context.WhatKind); + resolver.reporter.Error(MessageSource.Resolver, e, "a recursive call from {0} {1} can go only to other {1}s", article, context.WhatKind); } else if (cp != CallingPosition.Positive) { var msg = string.Format("{0} {1} can be called recursively only in positive positions", article, context.WhatKind); if (cp == CallingPosition.Neither) { @@ -2603,10 +2487,10 @@ namespace Microsoft.Dafny } else { // the fixpoint-call is not inside an quantifier, so don't bother mentioning the part of existentials/universals in the error message } - Error(e, msg); + resolver.reporter.Error(MessageSource.Resolver, e, msg); } else { e.CoCall = FunctionCallExpr.CoCallResolution.Yes; - ReportAdditionalInformation(e.tok, e.Function.Name + "#[_k - 1]", e.Function.Name.Length); + resolver.reporter.Info(MessageSource.Resolver, e.tok, e.Function.Name + "#[_k - 1]"); } } // do the sub-parts with cp := Neither @@ -2621,7 +2505,7 @@ namespace Microsoft.Dafny if (ModuleDefinition.InSameSCC(context, s.Method)) { // we're looking at a recursive call var article = context is InductivePredicate ? "an" : "a"; - Error(stmt.Tok, "a recursive call from {0} {1} can go only to other {1}s", article, context.WhatKind); + resolver.reporter.Error(MessageSource.Resolver, stmt.Tok, "a recursive call from {0} {1} can go only to other {1}s", article, context.WhatKind); } // do the sub-parts with the same "cp" return true; @@ -2662,7 +2546,7 @@ namespace Microsoft.Dafny if (ModuleDefinition.InSameSCC(context, s.Method)) { // we're looking at a recursive call (to a non-fixpoint-lemma) var article = context is InductiveLemma ? "an" : "a"; - Error(s.Tok, "a recursive call from {0} {1} can go only to other {1}s and prefix lemmas", article, context.WhatKind); + resolver.reporter.Error(MessageSource.Resolver, s.Tok, "a recursive call from {0} {1} can go only to other {1}s and prefix lemmas", article, context.WhatKind); } } } @@ -2674,7 +2558,7 @@ namespace Microsoft.Dafny // the call goes from a colemma context to a non-colemma callee if (ModuleDefinition.InSameSCC(context, e.Function)) { // we're looking at a recursive call (to a non-colemma) - Error(e.tok, "a recursive call from a colemma can go only to other colemmas and prefix lemmas"); + resolver.reporter.Error(MessageSource.Resolver, e.tok, "a recursive call from a colemma can go only to other colemmas and prefix lemmas"); } } } @@ -2733,7 +2617,7 @@ namespace Microsoft.Dafny foreach (var formalTypeArg in s.Method.TypeArgs) { var actualTypeArg = s.MethodSelect.TypeArgumentSubstitutions()[formalTypeArg]; if (formalTypeArg.MustSupportEquality && !actualTypeArg.SupportsEquality) { - Error(s.Tok, "type parameter {0} ({1}) passed to method {2} must support equality (got {3}){4}", i, formalTypeArg.Name, s.Method.Name, actualTypeArg, TypeEqualityErrorMessageHint(actualTypeArg)); + resolver.reporter.Error(MessageSource.Resolver, s.Tok, "type parameter {0} ({1}) passed to method {2} must support equality (got {3}){4}", i, formalTypeArg.Name, s.Method.Name, actualTypeArg, TypeEqualityErrorMessageHint(actualTypeArg)); } i++; } @@ -2788,9 +2672,9 @@ namespace Microsoft.Dafny } else if (e1 != null && e1.Arguments.Count == 0) { // oh yeah! } else if (!t0.SupportsEquality) { - Error(e.E0, "{0} can only be applied to expressions of types that support equality (got {1}){2}", BinaryExpr.OpcodeString(e.Op), t0, TypeEqualityErrorMessageHint(t0)); + resolver.reporter.Error(MessageSource.Resolver, e.E0, "{0} can only be applied to expressions of types that support equality (got {1}){2}", BinaryExpr.OpcodeString(e.Op), t0, TypeEqualityErrorMessageHint(t0)); } else if (!t1.SupportsEquality) { - Error(e.E1, "{0} can only be applied to expressions of types that support equality (got {1}){2}", BinaryExpr.OpcodeString(e.Op), t1, TypeEqualityErrorMessageHint(t1)); + resolver.reporter.Error(MessageSource.Resolver, e.E1, "{0} can only be applied to expressions of types that support equality (got {1}){2}", BinaryExpr.OpcodeString(e.Op), t1, TypeEqualityErrorMessageHint(t1)); } break; default: @@ -2803,12 +2687,12 @@ namespace Microsoft.Dafny case BinaryExpr.ResolvedOpcode.Prefix: case BinaryExpr.ResolvedOpcode.ProperPrefix: if (!t1.SupportsEquality) { - Error(e.E1, "{0} can only be applied to expressions of sequence types that support equality (got {1}){2}", BinaryExpr.OpcodeString(e.Op), t1, TypeEqualityErrorMessageHint(t1)); + resolver.reporter.Error(MessageSource.Resolver, e.E1, "{0} can only be applied to expressions of sequence types that support equality (got {1}){2}", BinaryExpr.OpcodeString(e.Op), t1, TypeEqualityErrorMessageHint(t1)); } else if (!t0.SupportsEquality) { if (e.ResolvedOp == BinaryExpr.ResolvedOpcode.InSet || e.ResolvedOp == BinaryExpr.ResolvedOpcode.NotInSeq) { - Error(e.E0, "{0} can only be applied to expressions of types that support equality (got {1}){2}", BinaryExpr.OpcodeString(e.Op), t0, TypeEqualityErrorMessageHint(t0)); + resolver.reporter.Error(MessageSource.Resolver, e.E0, "{0} can only be applied to expressions of types that support equality (got {1}){2}", BinaryExpr.OpcodeString(e.Op), t0, TypeEqualityErrorMessageHint(t0)); } else { - Error(e.E0, "{0} can only be applied to expressions of sequence types that support equality (got {1}){2}", BinaryExpr.OpcodeString(e.Op), t0, TypeEqualityErrorMessageHint(t0)); + resolver.reporter.Error(MessageSource.Resolver, e.E0, "{0} can only be applied to expressions of sequence types that support equality (got {1}){2}", BinaryExpr.OpcodeString(e.Op), t0, TypeEqualityErrorMessageHint(t0)); } } break; @@ -2834,7 +2718,7 @@ namespace Microsoft.Dafny foreach (var tp in ((ICallable)e.Member).TypeArgs) { var actualTp = e.TypeApplication[e.Member.EnclosingClass.TypeArgs.Count + i]; if (tp.MustSupportEquality && !actualTp.SupportsEquality) { - Error(e.tok, "type parameter {0} ({1}) passed to {5} '{2}' must support equality (got {3}){4}", i, tp.Name, e.Member.Name, actualTp, TypeEqualityErrorMessageHint(actualTp), e.Member.WhatKind); + resolver.reporter.Error(MessageSource.Resolver, e.tok, "type parameter {0} ({1}) passed to {5} '{2}' must support equality (got {3}){4}", i, tp.Name, e.Member.Name, actualTp, TypeEqualityErrorMessageHint(actualTp), e.Member.WhatKind); } i++; } @@ -2846,7 +2730,7 @@ namespace Microsoft.Dafny foreach (var formalTypeArg in e.Function.TypeArgs) { var actualTypeArg = e.TypeArgumentSubstitutions[formalTypeArg]; if (formalTypeArg.MustSupportEquality && !actualTypeArg.SupportsEquality) { - Error(e.tok, "type parameter {0} ({1}) passed to function {2} must support equality (got {3}){4}", i, formalTypeArg.Name, e.Function.Name, actualTypeArg, TypeEqualityErrorMessageHint(actualTypeArg)); + resolver.reporter.Error(MessageSource.Resolver, e.tok, "type parameter {0} ({1}) passed to function {2} must support equality (got {3}){4}", i, formalTypeArg.Name, e.Function.Name, actualTypeArg, TypeEqualityErrorMessageHint(actualTypeArg)); } i++; } @@ -2878,21 +2762,21 @@ namespace Microsoft.Dafny var st = (SetType)type; var argType = st.Arg; if (!argType.SupportsEquality) { - Error(tok, "{2}set argument type must support equality (got {0}){1}", argType, TypeEqualityErrorMessageHint(argType), st.Finite ? "" : "i"); + resolver.reporter.Error(MessageSource.Resolver, tok, "{2}set argument type must support equality (got {0}){1}", argType, TypeEqualityErrorMessageHint(argType), st.Finite ? "" : "i"); } CheckEqualityTypes_Type(tok, argType); } else if (type is MultiSetType) { var argType = ((MultiSetType)type).Arg; if (!argType.SupportsEquality) { - Error(tok, "multiset argument type must support equality (got {0}){1}", argType, TypeEqualityErrorMessageHint(argType)); + resolver.reporter.Error(MessageSource.Resolver, tok, "multiset argument type must support equality (got {0}){1}", argType, TypeEqualityErrorMessageHint(argType)); } CheckEqualityTypes_Type(tok, argType); } else if (type is MapType) { var mt = (MapType)type; if (!mt.Domain.SupportsEquality) { - Error(tok, "{2}map domain type must support equality (got {0}){1}", mt.Domain, TypeEqualityErrorMessageHint(mt.Domain), mt.Finite ? "" : "i"); + resolver.reporter.Error(MessageSource.Resolver, tok, "{2}map domain type must support equality (got {0}){1}", mt.Domain, TypeEqualityErrorMessageHint(mt.Domain), mt.Finite ? "" : "i"); } CheckEqualityTypes_Type(tok, mt.Domain); CheckEqualityTypes_Type(tok, mt.Range); @@ -2918,7 +2802,7 @@ namespace Microsoft.Dafny foreach (var argType in udt.TypeArgs) { var formalTypeArg = formalTypeArgs[i]; if (formalTypeArg.MustSupportEquality && !argType.SupportsEquality) { - Error(tok, "type parameter {0} ({1}) passed to type {2} must support equality (got {3}){4}", i, formalTypeArg.Name, udt.ResolvedClass.Name, argType, TypeEqualityErrorMessageHint(argType)); + resolver.reporter.Error(MessageSource.Resolver, tok, "type parameter {0} ({1}) passed to type {2} must support equality (got {3}){4}", i, formalTypeArg.Name, udt.ResolvedClass.Name, argType, TypeEqualityErrorMessageHint(argType)); } CheckEqualityTypes_Type(tok, argType); i++; @@ -3007,10 +2891,10 @@ namespace Microsoft.Dafny for (int i = 0; i < cs.Method.Ins.Count; i++) { argsSubstMap.Add(cs.Method.Ins[i], cs.Args[i]); } - var substituter = new Translator.AlphaConverting_Substituter(cs.Receiver, argsSubstMap, new Dictionary(), new Translator()); + var substituter = new Translator.AlphaConverting_Substituter(cs.Receiver, argsSubstMap, new Dictionary(), new Translator(resolver.reporter)); foreach (var ens in cs.Method.Ens) { var p = substituter.Substitute(ens.E); // substitute the call's actuals for the method's formals - resolver.ReportAdditionalInformation(s.Tok, "ensures " + Printer.ExprToString(p) + ";", s.Tok.val.Length); + resolver.reporter.Info(MessageSource.Resolver, s.Tok, "ensures " + Printer.ExprToString(p) + ";"); } } } @@ -3088,26 +2972,26 @@ namespace Microsoft.Dafny currentClass = cl; if (cl.TraitsTyp.Count > 0 && cl.TypeArgs.Count > 0) { - Error(cl.tok, "sorry, traits are currently supported only for classes that take no type arguments"); // TODO: do the work to remove this limitation + reporter.Error(MessageSource.Resolver, cl.tok, "sorry, traits are currently supported only for classes that take no type arguments"); // TODO: do the work to remove this limitation } // Resolve names of traits extended foreach (var tt in cl.TraitsTyp) { - var prevErrorCount = ErrorCount; + var prevErrorCount = reporter.Count(ErrorLevel.Error); ResolveType(cl.tok, tt, new NoContext(cl.Module), ResolveTypeOptionEnum.DontInfer, null); - if (ErrorCount == prevErrorCount) { + if (reporter.Count(ErrorLevel.Error) == prevErrorCount) { var udt = tt as UserDefinedType; if (udt != null && udt.ResolvedClass is TraitDecl) { var trait = (TraitDecl)udt.ResolvedClass; //disallowing inheritance in multi module case if (cl.Module != trait.Module) { - Error(udt.tok, "class '{0}' is in a different module than trait '{1}'. A class may only extend a trait in the same module.", cl.Name, trait.FullName); + reporter.Error(MessageSource.Resolver, udt.tok, "class '{0}' is in a different module than trait '{1}'. A class may only extend a trait in the same module.", cl.Name, trait.FullName); } else { // all is good cl.TraitsObj.Add(trait); } } else { - Error(udt != null ? udt.tok : cl.tok, "a class can only extend traits (found '{0}')", tt); + reporter.Error(MessageSource.Resolver, udt != null ? udt.tok : cl.tok, "a class can only extend traits (found '{0}')", tt); } } } @@ -3150,12 +3034,12 @@ namespace Microsoft.Dafny } else if (member is Function) { var f = (Function)member; - var ec = ErrorCount; + var ec = reporter.Count(ErrorLevel.Error); allTypeParameters.PushMarker(); ResolveTypeParameters(f.TypeArgs, true, f); ResolveFunctionSignature(f); allTypeParameters.PopMarker(); - if (f is FixpointPredicate && ec == ErrorCount) { + if (f is FixpointPredicate && ec == reporter.Count(ErrorLevel.Error)) { var ff = ((FixpointPredicate)f).PrefixPredicate; ff.EnclosingClass = cl; allTypeParameters.PushMarker(); @@ -3166,13 +3050,13 @@ namespace Microsoft.Dafny } else if (member is Method) { var m = (Method)member; - var ec = ErrorCount; + var ec = reporter.Count(ErrorLevel.Error); allTypeParameters.PushMarker(); ResolveTypeParameters(m.TypeArgs, true, m); ResolveMethodSignature(m); allTypeParameters.PopMarker(); var com = m as FixpointLemma; - if (com != null && com.PrefixLemma != null && ec == ErrorCount) { + if (com != null && com.PrefixLemma != null && ec == reporter.Count(ErrorLevel.Error)) { var mm = com.PrefixLemma; // resolve signature of the prefix lemma mm.EnclosingClass = cl; @@ -3193,7 +3077,7 @@ namespace Microsoft.Dafny void InheritTraitMembers(ClassDecl cl) { Contract.Requires(cl != null); - var refinementTransformer = new RefinementTransformer(this, AdditionalInformationReporter, null); + var refinementTransformer = new RefinementTransformer(reporter); //merging class members with parent members if any var clMembers = classMembers[cl]; foreach (TraitDecl trait in cl.TraitsObj) { @@ -3213,37 +3097,37 @@ namespace Microsoft.Dafny } else if (traitMember is Function) { var func = (Function)traitMember; if (func.Body == null) { - Error(cl.tok, "class '{0}' does not implement trait function '{1}.{2}'", cl.Name, trait.Name, traitMember.Name); + reporter.Error(MessageSource.Resolver, cl.tok, "class '{0}' does not implement trait function '{1}.{2}'", cl.Name, trait.Name, traitMember.Name); } else if (!func.IsGhost && !func.IsStatic) { cl.InheritedMembers.Add(func); } } else if (traitMember is Method) { var method = (Method)traitMember; if (method.Body == null) { - Error(cl.tok, "class '{0}' does not implement trait method '{1}.{2}'", cl.Name, trait.Name, traitMember.Name); + reporter.Error(MessageSource.Resolver, cl.tok, "class '{0}' does not implement trait method '{1}.{2}'", cl.Name, trait.Name, traitMember.Name); } else if (!method.IsGhost && !method.IsStatic) { cl.InheritedMembers.Add(method); } } } else if (clMember.EnclosingClass != cl) { // The class inherits the member from two places - Error(clMember.tok, "member name '{0}' in class '{1}' inherited from both traits '{2}' and '{3}'", traitMember.Name, cl.Name, clMember.EnclosingClass.Name, trait.Name); + reporter.Error(MessageSource.Resolver, clMember.tok, "member name '{0}' in class '{1}' inherited from both traits '{2}' and '{3}'", traitMember.Name, cl.Name, clMember.EnclosingClass.Name, trait.Name); } else if (traitMember is Field) { // The class is not allowed to do anything with the field other than silently inherit it. if (clMember is Field) { - Error(clMember.tok, "field '{0}' is inherited from trait '{1}' and is not allowed to be re-declared", traitMember.Name, trait.Name); + reporter.Error(MessageSource.Resolver, clMember.tok, "field '{0}' is inherited from trait '{1}' and is not allowed to be re-declared", traitMember.Name, trait.Name); } else { - Error(clMember.tok, "member name '{0}' in class '{1}' clashes with inherited field from trait '{2}'", traitMember.Name, cl.Name, trait.Name); + reporter.Error(MessageSource.Resolver, clMember.tok, "member name '{0}' in class '{1}' clashes with inherited field from trait '{2}'", traitMember.Name, cl.Name, trait.Name); } } else if (traitMember is Method) { var traitMethod = (Method)traitMember; if (traitMethod.Body != null) { // The method was defined in the trait, so the class is not allowed to do anything with the method other than silently inherit it. - Error(clMember.tok, "member '{0}' in class '{1}' overrides fully defined method inherited from trait '{2}'", clMember.Name, cl.Name, trait.Name); + reporter.Error(MessageSource.Resolver, clMember.tok, "member '{0}' in class '{1}' overrides fully defined method inherited from trait '{2}'", clMember.Name, cl.Name, trait.Name); } else if (!(clMember is Method)) { - Error(clMember.tok, "non-method member '{0}' overrides method '{1}' inherited from trait '{2}'", clMember.Name, traitMethod.Name, trait.Name); + reporter.Error(MessageSource.Resolver, clMember.tok, "non-method member '{0}' overrides method '{1}' inherited from trait '{2}'", clMember.Name, traitMethod.Name, trait.Name); } else { var classMethod = (Method)clMember; classMethod.OverriddenMethod = traitMethod; @@ -3255,7 +3139,7 @@ namespace Microsoft.Dafny var traitMethodAllowsNonTermination = Contract.Exists(traitMethod.Decreases.Expressions, e => e is WildcardExpr); var classMethodAllowsNonTermination = Contract.Exists(classMethod.Decreases.Expressions, e => e is WildcardExpr); if (classMethodAllowsNonTermination && !traitMethodAllowsNonTermination) { - Error(classMethod.tok, "not allowed to override a terminating method with a possibly non-terminating method ('{0}')", classMethod.Name); + reporter.Error(MessageSource.Resolver, classMethod.tok, "not allowed to override a terminating method with a possibly non-terminating method ('{0}')", classMethod.Name); } } @@ -3263,9 +3147,9 @@ namespace Microsoft.Dafny var traitFunction = (Function)traitMember; if (traitFunction.Body != null) { // The function was defined in the trait, so the class is not allowed to do anything with the function other than silently inherit it. - Error(clMember.tok, "member '{0}' in class '{1}' overrides fully defined function inherited from trait '{2}'", clMember.Name, cl.Name, trait.Name); + reporter.Error(MessageSource.Resolver, clMember.tok, "member '{0}' in class '{1}' overrides fully defined function inherited from trait '{2}'", clMember.Name, cl.Name, trait.Name); } else if (!(clMember is Function)) { - Error(clMember.tok, "non-function member '{0}' overrides function '{1}' inherited from trait '{2}'", clMember.Name, traitFunction.Name, trait.Name); + reporter.Error(MessageSource.Resolver, clMember.tok, "non-function member '{0}' overrides function '{1}' inherited from trait '{2}'", clMember.Name, traitFunction.Name, trait.Name); } else { var classFunction = (Function)clMember; classFunction.OverriddenFunction = traitFunction; @@ -3298,12 +3182,12 @@ namespace Microsoft.Dafny } else if (member is Function) { var f = (Function)member; - var ec = ErrorCount; + var ec = reporter.Count(ErrorLevel.Error); allTypeParameters.PushMarker(); ResolveTypeParameters(f.TypeArgs, false, f); ResolveFunction(f); allTypeParameters.PopMarker(); - if (f is FixpointPredicate && ec == ErrorCount) { + if (f is FixpointPredicate && ec == reporter.Count(ErrorLevel.Error)) { var ff = ((FixpointPredicate)f).PrefixPredicate; allTypeParameters.PushMarker(); ResolveTypeParameters(ff.TypeArgs, false, ff); @@ -3313,7 +3197,7 @@ namespace Microsoft.Dafny } else if (member is Method) { var m = (Method)member; - var ec = ErrorCount; + var ec = reporter.Count(ErrorLevel.Error); allTypeParameters.PushMarker(); ResolveTypeParameters(m.TypeArgs, false, m); ResolveMethod(m); @@ -3420,7 +3304,7 @@ namespace Microsoft.Dafny // whatever is in scc-cleared now failed to pass the test foreach (var dt in scc) { if (dt.DefaultCtor == null) { - Error(dt, "because of cyclic dependencies among constructor argument types, no instances of datatype '{0}' can be constructed", dt.Name); + reporter.Error(MessageSource.Resolver, dt, "because of cyclic dependencies among constructor argument types, no instances of datatype '{0}' can be constructed", dt.Name); } } return; @@ -3598,12 +3482,12 @@ namespace Microsoft.Dafny Contract.Requires(args != null); foreach (var arg in args) { Contract.Assert(arg != null); - int prevErrors = ErrorCount; + int prevErrors = reporter.Count(ErrorLevel.Error); ResolveExpression(arg, opts); if (!allowGhosts) { CheckIsNonGhost(arg); } - if (prevErrors == ErrorCount) { + if (prevErrors == reporter.Count(ErrorLevel.Error)) { CheckTypeInference(arg); } } @@ -3623,9 +3507,9 @@ namespace Microsoft.Dafny var r = allTypeParameters.Push(tp.Name, tp); if (emitErrors) { if (r == Scope.PushResult.Duplicate) { - Error(tp, "Duplicate type-parameter name: {0}", tp.Name); + reporter.Error(MessageSource.Resolver, tp, "Duplicate type-parameter name: {0}", tp.Name); } else if (r == Scope.PushResult.Shadow) { - Warning(tp.tok, "Shadowed type-parameter name: {0}", tp.Name); + reporter.Warning(MessageSource.Resolver, tp.tok, "Shadowed type-parameter name: {0}", tp.Name); } } } @@ -3649,10 +3533,10 @@ namespace Microsoft.Dafny case Scope.PushResult.Success: break; case Scope.PushResult.Duplicate: - Error(tok, "Duplicate {0} name: {1}", kind, name); + reporter.Error(MessageSource.Resolver, tok, "Duplicate {0} name: {1}", kind, name); break; case Scope.PushResult.Shadow: - Warning(tok, "Shadowed {0} name: {1}", kind, name); + reporter.Warning(MessageSource.Resolver, tok, "Shadowed {0} name: {1}", kind, name); break; } } @@ -3664,7 +3548,7 @@ namespace Microsoft.Dafny Contract.Requires(f != null); scope.PushMarker(); if (f.SignatureIsOmitted) { - Error(f, "function signature can be omitted only in refining functions"); + reporter.Error(MessageSource.Resolver, f, "function signature can be omitted only in refining functions"); } var option = f.TypeArgs.Count == 0 ? new ResolveTypeOption(f) : new ResolveTypeOption(ResolveTypeOptionEnum.AllowPrefix); foreach (Formal p in f.Formals) { @@ -3692,7 +3576,7 @@ namespace Microsoft.Dafny ResolveExpression(r, new ResolveOpts(f, false, true)); Contract.Assert(r.Type != null); // follows from postcondition of ResolveExpression if (!UnifyTypes(r.Type, Type.Bool)) { - Error(r, "Precondition must be a boolean (got {0})", r.Type); + reporter.Error(MessageSource.Resolver, r, "Precondition must be a boolean (got {0})", r.Type); } } foreach (FrameExpression fr in f.Reads) { @@ -3702,7 +3586,7 @@ namespace Microsoft.Dafny ResolveExpression(r, new ResolveOpts(f, false, true)); // since this is a function, the postcondition is still a one-state predicate Contract.Assert(r.Type != null); // follows from postcondition of ResolveExpression if (!UnifyTypes(r.Type, Type.Bool)) { - Error(r, "Postcondition must be a boolean (got {0})", r.Type); + reporter.Error(MessageSource.Resolver, r, "Postcondition must be a boolean (got {0})", r.Type); } } ResolveAttributes(f.Decreases.Attributes, new ResolveOpts(f, false, true)); @@ -3711,14 +3595,14 @@ namespace Microsoft.Dafny // any type is fine } if (f.Body != null) { - var prevErrorCount = ErrorCount; + var prevErrorCount = reporter.Count(ErrorLevel.Error); ResolveExpression(f.Body, new ResolveOpts(f, false)); - if (!f.IsGhost && prevErrorCount == ErrorCount) { + if (!f.IsGhost && prevErrorCount == reporter.Count(ErrorLevel.Error)) { CheckIsNonGhost(f.Body); } Contract.Assert(f.Body.Type != null); // follows from postcondition of ResolveExpression if (!UnifyTypes(f.Body.Type, f.ResultType)) { - Error(f, "Function body type mismatch (expected {0}, got {1})", f.ResultType, f.Body.Type); + reporter.Error(MessageSource.Resolver, f, "Function body type mismatch (expected {0}, got {1})", f.ResultType, f.Body.Type); } } scope.PopMarker(); @@ -3746,7 +3630,7 @@ namespace Microsoft.Dafny t = collType.Arg; } if (!UnifyTypes(t, new ObjectType())) { - Error(fe.E, "a {0}-clause expression must denote an object or a collection of objects (instead got {1})", readsFrame ? "reads" : "modifies", fe.E.Type); + reporter.Error(MessageSource.Resolver, fe.E, "a {0}-clause expression must denote an object or a collection of objects (instead got {1})", readsFrame ? "reads" : "modifies", fe.E.Type); } else if (fe.FieldName != null) { NonProxyType nptype; MemberDecl member = ResolveMember(fe.E.tok, t, fe.FieldName, out nptype); @@ -3754,9 +3638,9 @@ namespace Microsoft.Dafny if (member == null) { // error has already been reported by ResolveMember } else if (!(member is Field)) { - Error(fe.E, "member {0} in type {1} does not refer to a field", fe.FieldName, ctype.Name); + reporter.Error(MessageSource.Resolver, fe.E, "member {0} in type {1} does not refer to a field", fe.FieldName, ctype.Name); } else if (!readsFrame && isGhostContext && !member.IsGhost) { - Error(fe.E, "in a ghost context, only ghost fields can be mentioned as modifies frame targets ({0})", fe.FieldName); + reporter.Error(MessageSource.Resolver, fe.E, "in a ghost context, only ghost fields can be mentioned as modifies frame targets ({0})", fe.FieldName); } else { Contract.Assert(ctype != null && ctype.ResolvedClass != null); // follows from postcondition of ResolveMember fe.Field = (Field)member; @@ -3771,7 +3655,7 @@ namespace Microsoft.Dafny Contract.Requires(m != null); scope.PushMarker(); if (m.SignatureIsOmitted) { - Error(m, "method signature can be omitted only in refining methods"); + reporter.Error(MessageSource.Resolver, m, "method signature can be omitted only in refining methods"); } var option = m.TypeArgs.Count == 0 ? new ResolveTypeOption(m) : new ResolveTypeOption(ResolveTypeOptionEnum.AllowPrefix); // resolve in-parameters @@ -3812,14 +3696,14 @@ namespace Microsoft.Dafny ResolveExpression(e.E, new ResolveOpts(m, false, true)); Contract.Assert(e.E.Type != null); // follows from postcondition of ResolveExpression if (!UnifyTypes(e.E.Type, Type.Bool)) { - Error(e.E, "Precondition must be a boolean (got {0})", e.E.Type); + reporter.Error(MessageSource.Resolver, e.E, "Precondition must be a boolean (got {0})", e.E.Type); } } ResolveAttributes(m.Mod.Attributes, new ResolveOpts(m, false, true)); foreach (FrameExpression fe in m.Mod.Expressions) { ResolveFrameExpression(fe, false, m.IsGhost, m); if (m is Lemma || m is FixpointLemma) { - Error(fe.tok, "{0}s are not allowed to have modifies clauses", m.WhatKind); + reporter.Error(MessageSource.Resolver, fe.tok, "{0}s are not allowed to have modifies clauses", m.WhatKind); } } ResolveAttributes(m.Decreases.Attributes, new ResolveOpts(m, false, true)); @@ -3827,7 +3711,7 @@ namespace Microsoft.Dafny ResolveExpression(e, new ResolveOpts(m, false, true)); // any type is fine if (m.IsGhost && e is WildcardExpr) { - Error(e, "'decreases *' is not allowed on ghost methods"); + reporter.Error(MessageSource.Resolver, e, "'decreases *' is not allowed on ghost methods"); } } @@ -3835,7 +3719,7 @@ namespace Microsoft.Dafny // Don't care about any duplication errors among the out-parameters, since they have already been reported scope.PushMarker(); if (m is FixpointLemma && m.Outs.Count != 0) { - Error(m.Outs[0].tok, "{0}s are not allowed to have out-parameters", m.WhatKind); + reporter.Error(MessageSource.Resolver, m.Outs[0].tok, "{0}s are not allowed to have out-parameters", m.WhatKind); } else { foreach (Formal p in m.Outs) { scope.Push(p.Name, p); @@ -3848,7 +3732,7 @@ namespace Microsoft.Dafny ResolveExpression(e.E, new ResolveOpts(m, true, true)); Contract.Assert(e.E.Type != null); // follows from postcondition of ResolveExpression if (!UnifyTypes(e.E.Type, Type.Bool)) { - Error(e.E, "Postcondition must be a boolean (got {0})", e.E.Type); + reporter.Error(MessageSource.Resolver, e.E, "Postcondition must be a boolean (got {0})", e.E.Type); } } @@ -3896,7 +3780,7 @@ namespace Microsoft.Dafny Contract.Requires(iter != null); scope.PushMarker(); if (iter.SignatureIsOmitted) { - Error(iter, "iterator signature can be omitted only in refining methods"); + reporter.Error(MessageSource.Resolver, iter, "iterator signature can be omitted only in refining methods"); } var option = iter.TypeArgs.Count == 0 ? new ResolveTypeOption(iter) : new ResolveTypeOption(ResolveTypeOptionEnum.AllowPrefix); // resolve the types of the parameters @@ -3918,7 +3802,7 @@ namespace Microsoft.Dafny Contract.Requires(currentClass == null); Contract.Ensures(currentClass == null); - var initialErrorCount = ErrorCount; + var initialErrorCount = reporter.Count(ErrorLevel.Error); // Add in-parameters to the scope, but don't care about any duplication errors, since they have already been reported scope.PushMarker(); @@ -3937,7 +3821,7 @@ namespace Microsoft.Dafny var d = iter.DecreasesFields[i]; if (!UnifyTypes(d.Type, e.Type)) { // bummer, there was a use--and a bad use--of the field before, so this won't be the best of error messages - Error(e, "type of field {0} is {1}, but has been constrained elsewhere to be of type {2}", d.Name, e.Type, d.Type); + reporter.Error(MessageSource.Resolver, e, "type of field {0} is {1}, but has been constrained elsewhere to be of type {2}", d.Name, e.Type, d.Type); } } foreach (FrameExpression fe in iter.Reads.Expressions) { @@ -3950,7 +3834,7 @@ namespace Microsoft.Dafny ResolveExpression(e.E, new ResolveOpts(iter, false, true)); Contract.Assert(e.E.Type != null); // follows from postcondition of ResolveExpression if (!UnifyTypes(e.E.Type, Type.Bool)) { - Error(e.E, "Precondition must be a boolean (got {0})", e.E.Type); + reporter.Error(MessageSource.Resolver, e.E, "Precondition must be a boolean (got {0})", e.E.Type); } } @@ -3966,27 +3850,27 @@ namespace Microsoft.Dafny ResolveExpression(e.E, new ResolveOpts(iter, false, true)); Contract.Assert(e.E.Type != null); // follows from postcondition of ResolveExpression if (!UnifyTypes(e.E.Type, Type.Bool)) { - Error(e.E, "Yield precondition must be a boolean (got {0})", e.E.Type); + reporter.Error(MessageSource.Resolver, e.E, "Yield precondition must be a boolean (got {0})", e.E.Type); } } foreach (MaybeFreeExpression e in iter.YieldEnsures) { ResolveExpression(e.E, new ResolveOpts(iter, true, true)); Contract.Assert(e.E.Type != null); // follows from postcondition of ResolveExpression if (!UnifyTypes(e.E.Type, Type.Bool)) { - Error(e.E, "Yield postcondition must be a boolean (got {0})", e.E.Type); + reporter.Error(MessageSource.Resolver, e.E, "Yield postcondition must be a boolean (got {0})", e.E.Type); } } foreach (MaybeFreeExpression e in iter.Ensures) { ResolveExpression(e.E, new ResolveOpts(iter, true, true)); Contract.Assert(e.E.Type != null); // follows from postcondition of ResolveExpression if (!UnifyTypes(e.E.Type, Type.Bool)) { - Error(e.E, "Postcondition must be a boolean (got {0})", e.E.Type); + reporter.Error(MessageSource.Resolver, e.E, "Postcondition must be a boolean (got {0})", e.E.Type); } } ResolveAttributes(iter.Attributes, new ResolveOpts(iter, false, true)); - var postSpecErrorCount = ErrorCount; + var postSpecErrorCount = reporter.Count(ErrorLevel.Error); // Resolve body if (iter.Body != null) { @@ -4031,7 +3915,7 @@ namespace Microsoft.Dafny Expression frameSet = new SetDisplayExpr(iter.tok, true, modSetSingletons); foreach (var fr in iter.Reads.Expressions) { if (fr.FieldName != null) { - Error(fr.tok, "sorry, a reads clause for an iterator is not allowed to designate specific fields"); + reporter.Error(MessageSource.Resolver, fr.tok, "sorry, a reads clause for an iterator is not allowed to designate specific fields"); } else if (fr.E.Type.IsRefType) { modSetSingletons.Add(fr.E); } else { @@ -4046,7 +3930,7 @@ namespace Microsoft.Dafny frameSet = new SetDisplayExpr(iter.tok, true, modSetSingletons); foreach (var fr in iter.Modifies.Expressions) { if (fr.FieldName != null) { - Error(fr.tok, "sorry, a modifies clause for an iterator is not allowed to designate specific fields"); + reporter.Error(MessageSource.Resolver, fr.tok, "sorry, a modifies clause for an iterator is not allowed to designate specific fields"); } else if (fr.E.Type.IsRefType) { modSetSingletons.Add(fr.E); } else { @@ -4232,7 +4116,7 @@ namespace Microsoft.Dafny // nothing to resolve } else if (type is MapType) { var mt = (MapType)type; - var errorCount = ErrorCount; + var errorCount = reporter.Count(ErrorLevel.Error); int typeArgumentCount = 0; if (mt.HasTypeArg()) { ResolveType(tok, mt.Domain, context, option, defaultTypeArguments); @@ -4253,19 +4137,19 @@ namespace Microsoft.Dafny } // defaults and auto have been applied; check if we now have the right number of arguments if (2 != typeArgumentCount) { - Error(tok, "Wrong number of type arguments ({0} instead of 2) passed to type: {1}", typeArgumentCount, mt.CollectionTypeName); + reporter.Error(MessageSource.Resolver, tok, "Wrong number of type arguments ({0} instead of 2) passed to type: {1}", typeArgumentCount, mt.CollectionTypeName); // add proxy types, to make sure that MapType will have have a non-null Arg/Domain and Range if (typeArgumentCount == 0) { mt.SetTypeArg(new InferredTypeProxy()); } mt.SetRangetype(new InferredTypeProxy()); } - if (errorCount == ErrorCount && (mt.Domain.IsSubrangeType || mt.Range.IsSubrangeType)) { - Error(tok, "sorry, cannot instantiate collection type with a subrange type"); + if (errorCount == reporter.Count(ErrorLevel.Error) && (mt.Domain.IsSubrangeType || mt.Range.IsSubrangeType)) { + reporter.Error(MessageSource.Resolver, tok, "sorry, cannot instantiate collection type with a subrange type"); } } else if (type is CollectionType) { var t = (CollectionType)type; - var errorCount = ErrorCount; + var errorCount = reporter.Count(ErrorLevel.Error); if (t.HasTypeArg()) { ResolveType(tok, t.Arg, context, option, defaultTypeArguments); } else if (option.Opt != ResolveTypeOptionEnum.DontInfer) { @@ -4278,13 +4162,13 @@ namespace Microsoft.Dafny } if (!t.HasTypeArg()) { // defaults and auto have been applied; check if we now have the right number of arguments - Error(tok, "Wrong number of type arguments (0 instead of 1) passed to type: {0}", t.CollectionTypeName); + reporter.Error(MessageSource.Resolver, tok, "Wrong number of type arguments (0 instead of 1) passed to type: {0}", t.CollectionTypeName); // add a proxy type, to make sure that CollectionType will have have a non-null Arg t.SetTypeArg(new InferredTypeProxy()); } - if (errorCount == ErrorCount && t.Arg.IsSubrangeType) { - Error(tok, "sorry, cannot instantiate collection type with a subrange type"); + if (errorCount == reporter.Count(ErrorLevel.Error) && t.Arg.IsSubrangeType) { + reporter.Error(MessageSource.Resolver, tok, "sorry, cannot instantiate collection type with a subrange type"); } } else if (type is UserDefinedType) { @@ -4293,7 +4177,7 @@ namespace Microsoft.Dafny // Apparently, this type has already been resolved return null; } - var prevErrorCount = ErrorCount; + var prevErrorCount = reporter.Count(ErrorLevel.Error); if (t.NamePath is ExprDotName) { var ret = ResolveDotSuffix_Type((ExprDotName)t.NamePath, new ResolveOpts(context, true, true), allowDanglingDotName, option, defaultTypeArguments); if (ret != null) { @@ -4303,10 +4187,10 @@ namespace Microsoft.Dafny var s = (NameSegment)t.NamePath; ResolveNameSegment_Type(s, new ResolveOpts(context, true, true), option, defaultTypeArguments); } - if (ErrorCount == prevErrorCount) { + if (reporter.Count(ErrorLevel.Error) == prevErrorCount) { var r = t.NamePath.Resolved as Resolver_IdentifierExpr; if (r == null || !(r.Type is Resolver_IdentifierExpr.ResolverType_Type)) { - Error(t.tok, "expected type"); + reporter.Error(MessageSource.Resolver, t.tok, "expected type"); } else if (r.Type is Resolver_IdentifierExpr.ResolverType_Type && r.TypeParamDecl != null) { t.ResolvedParam = r.TypeParamDecl; } else if (r.Type is Resolver_IdentifierExpr.ResolverType_Type) { @@ -4328,7 +4212,7 @@ namespace Microsoft.Dafny caller.EnclosingModule.CallGraph.AddEdge(caller, dd); if (caller == dd) { // detect self-loops here, since they don't show up in the graph's SSC methods - Error(dd.tok, "recursive dependency involving a newtype: {0} -> {0}", dd.Name); + reporter.Error(MessageSource.Resolver, dd.tok, "recursive dependency involving a newtype: {0} -> {0}", dd.Name); } } t.ResolvedClass = dd; @@ -4343,7 +4227,7 @@ namespace Microsoft.Dafny } // defaults and auto have been applied; check if we now have the right number of arguments if (d.TypeArgs.Count != t.TypeArgs.Count) { - Error(t.tok, "Wrong number of type arguments ({0} instead of {1}) passed to {2}: {3}", t.TypeArgs.Count, d.TypeArgs.Count, d.WhatKind, t.Name); + reporter.Error(MessageSource.Resolver, t.tok, "Wrong number of type arguments ({0} instead of {1}) passed to {2}: {3}", t.TypeArgs.Count, d.TypeArgs.Count, d.WhatKind, t.Name); } } @@ -4839,14 +4723,14 @@ namespace Microsoft.Dafny ResolveExpression(s.Expr, new ResolveOpts(codeContext, true, true)); Contract.Assert(s.Expr.Type != null); // follows from postcondition of ResolveExpression if (!UnifyTypes(s.Expr.Type, Type.Bool)) { - Error(s.Expr, "condition is expected to be of type {0}, but is {1}", Type.Bool, s.Expr.Type); + reporter.Error(MessageSource.Resolver, s.Expr, "condition is expected to be of type {0}, but is {1}", Type.Bool, s.Expr.Type); } } else if (stmt is PrintStmt) { PrintStmt s = (PrintStmt)stmt; ResolveAttributeArgs(s.Args, new ResolveOpts(codeContext, false, specContextOnly), false); if (specContextOnly) { - Error(stmt, "print statement is not allowed in this context (because this is a ghost method or because the statement is guarded by a specification-only expression)"); + reporter.Error(MessageSource.Resolver, stmt, "print statement is not allowed in this context (because this is a ghost method or because the statement is guarded by a specification-only expression)"); } } else if (stmt is BreakStmt) { @@ -4854,17 +4738,17 @@ namespace Microsoft.Dafny if (s.TargetLabel != null) { Statement target = labeledStatements.Find(s.TargetLabel); if (target == null) { - Error(s, "break label is undefined or not in scope: {0}", s.TargetLabel); + reporter.Error(MessageSource.Resolver, s, "break label is undefined or not in scope: {0}", s.TargetLabel); } else { s.TargetStmt = target; bool targetIsLoop = target is WhileStmt || target is AlternativeLoopStmt; if (specContextOnly && !s.TargetStmt.IsGhost && !inSpecOnlyContext[s.TargetStmt]) { - Error(stmt, "ghost-context break statement is not allowed to break out of non-ghost " + (targetIsLoop ? "loop" : "structure")); + reporter.Error(MessageSource.Resolver, stmt, "ghost-context break statement is not allowed to break out of non-ghost " + (targetIsLoop ? "loop" : "structure")); } } } else { if (loopStack.Count < s.BreakCount) { - Error(s, "trying to break out of more loop levels than there are enclosing loops"); + reporter.Error(MessageSource.Resolver, s, "trying to break out of more loop levels than there are enclosing loops"); } else { Statement target = loopStack[loopStack.Count - s.BreakCount]; if (target.Labels == null) { @@ -4873,7 +4757,7 @@ namespace Microsoft.Dafny } s.TargetStmt = target; if (specContextOnly && !target.IsGhost && !inSpecOnlyContext[target]) { - Error(stmt, "ghost-context break statement is not allowed to break out of non-ghost loop"); + reporter.Error(MessageSource.Resolver, stmt, "ghost-context break statement is not allowed to break out of non-ghost loop"); } } } @@ -4881,11 +4765,11 @@ namespace Microsoft.Dafny } else if (stmt is ProduceStmt) { var kind = stmt is YieldStmt ? "yield" : "return"; if (stmt is YieldStmt && !(codeContext is IteratorDecl)) { - Error(stmt, "yield statement is allowed only in iterators"); + reporter.Error(MessageSource.Resolver, stmt, "yield statement is allowed only in iterators"); } else if (stmt is ReturnStmt && !(codeContext is Method)) { - Error(stmt, "return statement is allowed only in method"); + reporter.Error(MessageSource.Resolver, stmt, "return statement is allowed only in method"); } else if (specContextOnly && !codeContext.IsGhost) { - Error(stmt, "{0} statement is not allowed in this context (because it is guarded by a specification-only expression)", kind); + reporter.Error(MessageSource.Resolver, stmt, "{0} statement is not allowed in this context (because it is guarded by a specification-only expression)", kind); } var s = (ProduceStmt)stmt; if (s.rhss != null) { @@ -4893,7 +4777,7 @@ namespace Microsoft.Dafny if (cmc == null) { // an error has already been reported above } else if (cmc.Outs.Count != s.rhss.Count) { - Error(s, "number of {2} parameters does not match declaration (found {0}, expected {1})", s.rhss.Count, cmc.Outs.Count, kind); + reporter.Error(MessageSource.Resolver, s, "number of {2} parameters does not match declaration (found {0}, expected {1})", s.rhss.Count, cmc.Outs.Count, kind); } else { Contract.Assert(s.rhss.Count > 0); // Create a hidden update statement using the out-parameter formals, resolve the RHS, and check that the RHS is good. @@ -4986,24 +4870,24 @@ namespace Microsoft.Dafny { if (currentMethod == null) { - Error(local.Tok, "assumption variable can only be declared in a method"); + reporter.Error(MessageSource.Resolver, local.Tok, "assumption variable can only be declared in a method"); } if (!local.IsGhost) { - Error(local.Tok, "assumption variable must be ghost"); + reporter.Error(MessageSource.Resolver, local.Tok, "assumption variable must be ghost"); } if (!(local.Type.IsBoolType)) { - Error(s, "assumption variable must be of type 'bool'"); + reporter.Error(MessageSource.Resolver, s, "assumption variable must be of type 'bool'"); } } } } else if (stmt is AssignStmt) { AssignStmt s = (AssignStmt)stmt; - int prevErrorCount = ErrorCount; + int prevErrorCount = reporter.Count(ErrorLevel.Error); ResolveExpression(s.Lhs, new ResolveOpts(codeContext, true, specContextOnly)); // allow ghosts for now, tighted up below - bool lhsResolvedSuccessfully = ErrorCount == prevErrorCount; + bool lhsResolvedSuccessfully = reporter.Count(ErrorLevel.Error) == prevErrorCount; Contract.Assert(s.Lhs.Type != null); // follows from postcondition of ResolveExpression // check that LHS denotes a mutable variable or a field bool lvalueIsGhost = false; @@ -5016,7 +4900,7 @@ namespace Microsoft.Dafny lvalueIsGhost = var.IsGhost || codeContext.IsGhost; CheckIsLvalue(lhs, codeContext); if (!lvalueIsGhost && specContextOnly) { - Error(stmt, "Assignment to non-ghost variable is not allowed in this context (because this is a ghost method or because the statement is guarded by a specification-only expression)"); + reporter.Error(MessageSource.Resolver, stmt, "Assignment to non-ghost variable is not allowed in this context (because this is a ghost method or because the statement is guarded by a specification-only expression)"); } var localVar = var as LocalVariable; @@ -5035,7 +4919,7 @@ namespace Microsoft.Dafny } else { - Error(stmt, string.Format("there may be at most one assignment to an assumption variable, the RHS of which must match the expression \"{0} && \"", localVar.Name)); + reporter.Error(MessageSource.Resolver, stmt, string.Format("there may be at most one assignment to an assumption variable, the RHS of which must match the expression \"{0} && \"", localVar.Name)); } } } @@ -5045,12 +4929,12 @@ namespace Microsoft.Dafny lvalueIsGhost = fse.Member.IsGhost; if (!lvalueIsGhost) { if (specContextOnly) { - Error(stmt, "Assignment to non-ghost field is not allowed in this context (because this is a ghost method or because the statement is guarded by a specification-only expression)"); + reporter.Error(MessageSource.Resolver, stmt, "Assignment to non-ghost field is not allowed in this context (because this is a ghost method or because the statement is guarded by a specification-only expression)"); } else { // It is now that we wish we would have resolved s.Lhs to not allow ghosts. Too late, so we do // the next best thing. if (lhsResolvedSuccessfully && UsesSpecFeatures(fse.Obj)) { - Error(stmt, "Assignment to non-ghost field is not allowed to use specification-only expressions in the receiver"); + reporter.Error(MessageSource.Resolver, stmt, "Assignment to non-ghost field is not allowed to use specification-only expressions in the receiver"); } } } @@ -5062,14 +4946,14 @@ namespace Microsoft.Dafny if (lhsResolvedSuccessfully) { Contract.Assert(slhs.Seq.Type != null); if (specContextOnly) { - Error(stmt, "Assignment to array element is not allowed in this context (because this is a ghost method or because the statement is guarded by a specification-only expression)"); + reporter.Error(MessageSource.Resolver, stmt, "Assignment to array element is not allowed in this context (because this is a ghost method or because the statement is guarded by a specification-only expression)"); } CheckIsLvalue(slhs, codeContext); } } else if (lhs is MultiSelectExpr) { if (specContextOnly) { - Error(stmt, "Assignment to array element is not allowed in this context (because this is a ghost method or because the statement is guarded by a specification-only expression)"); + reporter.Error(MessageSource.Resolver, stmt, "Assignment to array element is not allowed in this context (because this is a ghost method or because the statement is guarded by a specification-only expression)"); } CheckIsLvalue(lhs, codeContext); @@ -5087,7 +4971,7 @@ namespace Microsoft.Dafny } Contract.Assert(rr.Expr.Type != null); // follows from postcondition of ResolveExpression if (!UnifyTypes(lhsType, rr.Expr.Type)) { - Error(stmt, "RHS (of type {0}) not assignable to LHS (of type {1})", rr.Expr.Type, lhsType); + reporter.Error(MessageSource.Resolver, stmt, "RHS (of type {0}) not assignable to LHS (of type {1})", rr.Expr.Type, lhsType); } } else if (s.Rhs is TypeRhs) { TypeRhs rr = (TypeRhs)s.Rhs; @@ -5105,7 +4989,7 @@ namespace Microsoft.Dafny } } if (!UnifyTypes(lhsType, t)) { - Error(stmt, "type {0} is not assignable to LHS (of type {1})", t, lhsType); + reporter.Error(MessageSource.Resolver, stmt, "type {0} is not assignable to LHS (of type {1})", t, lhsType); } } else if (s.Rhs is HavocRhs) { // nothing else to do @@ -5130,12 +5014,12 @@ namespace Microsoft.Dafny IfStmt s = (IfStmt)stmt; bool branchesAreSpecOnly = specContextOnly; if (s.Guard != null) { - int prevErrorCount = ErrorCount; + int prevErrorCount = reporter.Count(ErrorLevel.Error); ResolveExpression(s.Guard, new ResolveOpts(codeContext, true, specContextOnly)); Contract.Assert(s.Guard.Type != null); // follows from postcondition of ResolveExpression - bool successfullyResolved = ErrorCount == prevErrorCount; + bool successfullyResolved = reporter.Count(ErrorLevel.Error) == prevErrorCount; if (!UnifyTypes(s.Guard.Type, Type.Bool)) { - Error(s.Guard, "condition is expected to be of type {0}, but is {1}", Type.Bool, s.Guard.Type); + reporter.Error(MessageSource.Resolver, s.Guard, "condition is expected to be of type {0}, but is {1}", Type.Bool, s.Guard.Type); } if (!specContextOnly && successfullyResolved) { branchesAreSpecOnly = UsesSpecFeatures(s.Guard); @@ -5163,13 +5047,13 @@ namespace Microsoft.Dafny bool bodyMustBeSpecOnly = specContextOnly; var fvs = new HashSet(); if (s.Guard != null) { - int prevErrorCount = ErrorCount; + int prevErrorCount = reporter.Count(ErrorLevel.Error); ResolveExpression(s.Guard, new ResolveOpts(codeContext, true, specContextOnly)); Contract.Assert(s.Guard.Type != null); // follows from postcondition of ResolveExpression - bool successfullyResolved = ErrorCount == prevErrorCount; + bool successfullyResolved = reporter.Count(ErrorLevel.Error) == prevErrorCount; Translator.ComputeFreeVariables(s.Guard, fvs); if (!UnifyTypes(s.Guard.Type, Type.Bool)) { - Error(s.Guard, "condition is expected to be of type {0}, but is {1}", Type.Bool, s.Guard.Type); + reporter.Error(MessageSource.Resolver, s.Guard, "condition is expected to be of type {0}, but is {1}", Type.Bool, s.Guard.Type); } if (!specContextOnly && successfullyResolved) { bodyMustBeSpecOnly = UsesSpecFeatures(s.Guard); @@ -5182,7 +5066,7 @@ namespace Microsoft.Dafny Contract.Assert(inv.E.Type != null); // follows from postcondition of ResolveExpression Translator.ComputeFreeVariables(inv.E, fvs); if (!UnifyTypes(inv.E.Type, Type.Bool)) { - Error(inv.E, "invariant is expected to be of type {0}, but is {1}", Type.Bool, inv.E.Type); + reporter.Error(MessageSource.Resolver, inv.E, "invariant is expected to be of type {0}, but is {1}", Type.Bool, inv.E.Type); } } @@ -5191,9 +5075,9 @@ namespace Microsoft.Dafny ResolveExpression(e, new ResolveOpts(codeContext, true, true)); if (e is WildcardExpr) { if (bodyMustBeSpecOnly) { - Error(e, "'decreases *' is not allowed on ghost loops"); + reporter.Error(MessageSource.Resolver, e, "'decreases *' is not allowed on ghost loops"); } else if (!codeContext.AllowsNontermination && !DafnyOptions.O.Dafnycc) { - Error(e, "a possibly infinite loop is allowed only if the enclosing method is declared (with 'decreases *') to be possibly non-terminating"); + reporter.Error(MessageSource.Resolver, e, "a possibly infinite loop is allowed only if the enclosing method is declared (with 'decreases *') to be possibly non-terminating"); } } // any type is fine @@ -5225,7 +5109,7 @@ namespace Microsoft.Dafny } } text += "};"; // always terminate with a semi-colon - ReportAdditionalInformation(s.Tok, text, s.Tok.val.Length); + reporter.Info(MessageSource.Resolver, s.Tok, text); } } else if (stmt is AlternativeLoopStmt) { @@ -5235,7 +5119,7 @@ namespace Microsoft.Dafny ResolveExpression(inv.E, new ResolveOpts(codeContext, true, true)); Contract.Assert(inv.E.Type != null); // follows from postcondition of ResolveExpression if (!UnifyTypes(inv.E.Type, Type.Bool)) { - Error(inv.E, "invariant is expected to be of type {0}, but is {1}", Type.Bool, inv.E.Type); + reporter.Error(MessageSource.Resolver, inv.E, "invariant is expected to be of type {0}, but is {1}", Type.Bool, inv.E.Type); } } @@ -5243,9 +5127,9 @@ namespace Microsoft.Dafny ResolveExpression(e, new ResolveOpts(codeContext, true, true)); if (e is WildcardExpr) { if (s.IsGhost) { - Error(e, "'decreases *' is not allowed on ghost loops"); + reporter.Error(MessageSource.Resolver, e, "'decreases *' is not allowed on ghost loops"); } else if (!codeContext.AllowsNontermination && !DafnyOptions.O.Dafnycc) { - Error(e, "a possibly infinite loop is allowed only if the enclosing method is declared (with 'decreases *') to be possibly non-terminating"); + reporter.Error(MessageSource.Resolver, e, "a possibly infinite loop is allowed only if the enclosing method is declared (with 'decreases *') to be possibly non-terminating"); } } // any type is fine @@ -5254,7 +5138,7 @@ namespace Microsoft.Dafny } else if (stmt is ForallStmt) { var s = (ForallStmt)stmt; - int prevErrorCount = ErrorCount; + int prevErrorCount = reporter.Count(ErrorLevel.Error); scope.PushMarker(); foreach (BoundVar v in s.BoundVars) { ScopePushAndReport(scope, v, "local-variable"); @@ -5263,24 +5147,24 @@ namespace Microsoft.Dafny ResolveExpression(s.Range, new ResolveOpts(codeContext, true, specContextOnly)); Contract.Assert(s.Range.Type != null); // follows from postcondition of ResolveExpression if (!UnifyTypes(s.Range.Type, Type.Bool)) { - Error(stmt, "range restriction in forall statement must be of type bool (instead got {0})", s.Range.Type); + reporter.Error(MessageSource.Resolver, stmt, "range restriction in forall statement must be of type bool (instead got {0})", s.Range.Type); } foreach (var ens in s.Ens) { ResolveExpression(ens.E, new ResolveOpts(codeContext, true, true)); Contract.Assert(ens.E.Type != null); // follows from postcondition of ResolveExpression if (!UnifyTypes(ens.E.Type, Type.Bool)) { - Error(ens.E, "ensures condition is expected to be of type {0}, but is {1}", Type.Bool, ens.E.Type); + reporter.Error(MessageSource.Resolver, ens.E, "ensures condition is expected to be of type {0}, but is {1}", Type.Bool, ens.E.Type); } } // Since the range and postconditions are more likely to infer the types of the bound variables, resolve them // first (above) and only then resolve the attributes (below). ResolveAttributes(s.Attributes, new ResolveOpts(codeContext, true, true)); - bool bodyMustBeSpecOnly = specContextOnly || (prevErrorCount == ErrorCount && UsesSpecFeatures(s.Range)); - if (!bodyMustBeSpecOnly && prevErrorCount == ErrorCount) { + bool bodyMustBeSpecOnly = specContextOnly || (prevErrorCount == reporter.Count(ErrorLevel.Error) && UsesSpecFeatures(s.Range)); + if (!bodyMustBeSpecOnly && prevErrorCount == reporter.Count(ErrorLevel.Error)) { var missingBounds = new List(); CheckTypeInference(s.Range); // we need to resolve operators before the call to DiscoverBounds - s.Bounds = DiscoverBounds(s.Tok, s.BoundVars, s.Range, true, false, missingBounds); + s.Bounds = DiscoverBounds(s.Tok, s.BoundVars, s.Range, true, false, missingBounds, reporter); if (missingBounds.Count != 0) { bodyMustBeSpecOnly = true; } @@ -5299,7 +5183,7 @@ namespace Microsoft.Dafny } scope.PopMarker(); - if (prevErrorCount == ErrorCount) { + if (prevErrorCount == reporter.Count(ErrorLevel.Error)) { // determine the Kind and run some additional checks on the body if (s.Ens.Count != 0) { // The only supported kind with ensures clauses is Proof. @@ -5323,13 +5207,13 @@ namespace Microsoft.Dafny // add the conclusion of the calc as a free postcondition var result = ((CalcStmt)s0).Result; s.Ens.Add(new MaybeFreeExpression(result, true)); - ReportAdditionalInformation(s.Tok, "ensures " + Printer.ExprToString(result) + ";", s.Tok.val.Length); + reporter.Info(MessageSource.Resolver, s.Tok, "ensures " + Printer.ExprToString(result) + ";"); } else { s.Kind = ForallStmt.ParBodyKind.Proof; if (s.Body is BlockStmt && ((BlockStmt)s.Body).Body.Count == 0) { // an empty statement, so don't produce any warning } else { - Warning(s.Tok, "the conclusion of the body of this forall statement will not be known outside the forall statement; consider using an 'ensures' clause"); + reporter.Warning(MessageSource.Resolver, s.Tok, "the conclusion of the body of this forall statement will not be known outside the forall statement; consider using an 'ensures' clause"); } } } @@ -5351,7 +5235,7 @@ namespace Microsoft.Dafny s.IsGhost = specContextOnly; } else if (stmt is CalcStmt) { - var prevErrorCount = ErrorCount; + var prevErrorCount = reporter.Count(ErrorLevel.Error); CalcStmt s = (CalcStmt)stmt; s.IsGhost = true; if (s.Lines.Count > 0) { @@ -5359,12 +5243,12 @@ namespace Microsoft.Dafny ResolveExpression(e0, new ResolveOpts(codeContext, true, true)); Contract.Assert(e0.Type != null); // follows from postcondition of ResolveExpression for (int i = 1; i < s.Lines.Count; i++) { - if (i < s.Lines.Count - 1 || prevErrorCount == ErrorCount) { // do not resolve the dummy step if there were errors, it might generate more errors + if (i < s.Lines.Count - 1 || prevErrorCount == reporter.Count(ErrorLevel.Error)) { // do not resolve the dummy step if there were errors, it might generate more errors var e1 = s.Lines[i]; ResolveExpression(e1, new ResolveOpts(codeContext, true, true)); Contract.Assert(e1.Type != null); // follows from postcondition of ResolveExpression if (!UnifyTypes(e0.Type, e1.Type)) { - Error(e1, "all lines in a calculation must have the same type (got {0} after {1})", e1.Type, e0.Type); + reporter.Error(MessageSource.Resolver, e1, "all lines in a calculation must have the same type (got {0} after {1})", e1.Type, e0.Type); } else { var step = s.StepOps[i - 1].StepExpr(e0, e1); // Use custom line operator ResolveExpression(step, new ResolveOpts(codeContext, true, true)); @@ -5387,7 +5271,7 @@ namespace Microsoft.Dafny loopStack = prevLoopStack; } - if (prevErrorCount == ErrorCount && s.Lines.Count > 0) { + if (prevErrorCount == reporter.Count(ErrorLevel.Error) && s.Lines.Count > 0) { // do not build Result from the lines if there were errors, as it might be ill-typed and produce unnecessary resolution errors s.Result = s.ResultOp.StepExpr(s.Lines.First(), s.Lines.Last()); } else { @@ -5395,13 +5279,13 @@ namespace Microsoft.Dafny } ResolveExpression(s.Result, new ResolveOpts(codeContext, true, true)); Contract.Assert(s.Result != null); - Contract.Assert(prevErrorCount != ErrorCount || s.Steps.Count == s.Hints.Count); + Contract.Assert(prevErrorCount != reporter.Count(ErrorLevel.Error) || s.Steps.Count == s.Hints.Count); } else if (stmt is MatchStmt) { ResolveMatchStmt(stmt, specContextOnly, codeContext); } else if (stmt is SkeletonStatement) { var s = (SkeletonStatement)stmt; - Error(s.Tok, "skeleton statements are allowed only in refining methods"); + reporter.Error(MessageSource.Resolver, s.Tok, "skeleton statements are allowed only in refining methods"); // nevertheless, resolve the underlying statement; hey, why not if (s.S != null) { ResolveStatement(s.S, specContextOnly, codeContext); @@ -5416,10 +5300,10 @@ namespace Microsoft.Dafny DesugarMatchStmtWithTupleExpression(s); bool bodyIsSpecOnly = specContextOnly; - int prevErrorCount = ErrorCount; + int prevErrorCount = reporter.Count(ErrorLevel.Error); ResolveExpression(s.Source, new ResolveOpts(codeContext, true, specContextOnly)); Contract.Assert(s.Source.Type != null); // follows from postcondition of ResolveExpression - bool successfullyResolved = ErrorCount == prevErrorCount; + bool successfullyResolved = reporter.Count(ErrorLevel.Error) == prevErrorCount; if (!specContextOnly && successfullyResolved) { bodyIsSpecOnly = UsesSpecFeatures(s.Source); } @@ -5432,7 +5316,7 @@ namespace Microsoft.Dafny var subst = new Dictionary(); Dictionary ctors; if (dtd == null) { - Error(s.Source, "the type of the match source expression must be a datatype (instead found {0})", s.Source.Type); + reporter.Error(MessageSource.Resolver, s.Source, "the type of the match source expression must be a datatype (instead found {0})", s.Source.Type); ctors = null; } else { Contract.Assert(sourceType != null); // dtd and sourceType are set together above @@ -5462,15 +5346,15 @@ namespace Microsoft.Dafny if (ctors != null) { Contract.Assert(dtd != null); if (!ctors.TryGetValue(mc.Id, out ctor)) { - Error(mc.tok, "member {0} does not exist in datatype {1}", mc.Id, dtd.Name); + reporter.Error(MessageSource.Resolver, mc.tok, "member {0} does not exist in datatype {1}", mc.Id, dtd.Name); } else { Contract.Assert(ctor != null); // follows from postcondition of TryGetValue mc.Ctor = ctor; if (ctor.Formals.Count != mc.Arguments.Count) { - Error(mc.tok, "member {0} has wrong number of formals (found {1}, expected {2})", mc.Id, mc.Arguments.Count, ctor.Formals.Count); + reporter.Error(MessageSource.Resolver, mc.tok, "member {0} has wrong number of formals (found {1}, expected {2})", mc.Id, mc.Arguments.Count, ctor.Formals.Count); } if (memberNamesUsed.Contains(mc.Id)) { - Error(mc.tok, "member {0} appears in more than one case", mc.Id); + reporter.Error(MessageSource.Resolver, mc.tok, "member {0} appears in more than one case", mc.Id); } else { memberNamesUsed.Add(mc.Id); // add mc.Id to the set of names used } @@ -5486,7 +5370,7 @@ namespace Microsoft.Dafny Formal formal = ctor.Formals[i]; Type st = SubstType(formal.Type, subst); if (!UnifyTypes(v.Type, st)) { - Error(stmt, "the declared type of the formal ({0}) does not agree with the corresponding type in the constructor's signature ({1})", v.Type, st); + reporter.Error(MessageSource.Resolver, stmt, "the declared type of the formal ({0}) does not agree with the corresponding type in the constructor's signature ({1})", v.Type, st); } v.IsGhost = formal.IsGhost; @@ -5557,7 +5441,7 @@ namespace Microsoft.Dafny if (me.Source is DatatypeValue) { var e = (DatatypeValue)me.Source; if (e.Arguments.Count < 1) { - Error(me.Tok, "match source tuple needs at least 1 argument"); + reporter.Error(MessageSource.Resolver, me.Tok, "match source tuple needs at least 1 argument"); } else { Expression source = e.Arguments[0]; List cases = new List(); @@ -5566,7 +5450,7 @@ namespace Microsoft.Dafny bool keepOrigToken = true; foreach (MatchCaseStmt mc in me.Cases) { if (mc.CasePatterns == null || mc.CasePatterns.Count != e.Arguments.Count) { - Error(mc.tok, "case arguments count does not match source arguments count"); + reporter.Error(MessageSource.Resolver, mc.tok, "case arguments count does not match source arguments count"); } else { CasePattern cp = mc.CasePatterns[0]; List patterns; @@ -5723,7 +5607,7 @@ namespace Microsoft.Dafny ScopePushAndReport(scope, v, "parameter"); } else { if (scope.Find(v.Name) != null) { - Error(v, "Duplicate parameter name: {0}", v.Name); + reporter.Error(MessageSource.Resolver, v, "Duplicate parameter name: {0}", v.Name); } } } else { @@ -5938,26 +5822,26 @@ namespace Microsoft.Dafny } } s += ";"; // always terminate with a semi-colon, even in the case of an empty decreases clause - ReportAdditionalInformation(loopStmt.Tok, s, loopStmt.Tok.val.Length); + reporter.Info(MessageSource.Resolver, loopStmt.Tok, s); } } private void ResolveConcreteUpdateStmt(ConcreteUpdateStatement s, bool specContextOnly, ICodeContext codeContext) { Contract.Requires(codeContext != null); // First, resolve all LHS's and expression-looking RHS's. - int errorCountBeforeCheckingLhs = ErrorCount; + int errorCountBeforeCheckingLhs = reporter.Count(ErrorLevel.Error); var update = s as UpdateStmt; var lhsNameSet = new HashSet(); // used to check for duplicate identifiers on the left (full duplication checking for references and the like is done during verification) foreach (var lhs in s.Lhss) { - var ec = ErrorCount; + var ec = reporter.Count(ErrorLevel.Error); ResolveExpression(lhs, new ResolveOpts(codeContext, true, specContextOnly)); - if (ec == ErrorCount) { + if (ec == reporter.Count(ErrorLevel.Error)) { if (update == null && specContextOnly && !AssignStmt.LhsIsToGhost(lhs) && !codeContext.IsGhost) { - Error(lhs, "cannot assign to non-ghost variable in a ghost context"); + reporter.Error(MessageSource.Resolver, lhs, "cannot assign to non-ghost variable in a ghost context"); } if (lhs is SeqSelectExpr && !((SeqSelectExpr)lhs).SelectOne) { - Error(lhs, "cannot assign to a range of array elements (try the 'forall' statement)"); + reporter.Error(MessageSource.Resolver, lhs, "cannot assign to a range of array elements (try the 'forall' statement)"); } } } @@ -6018,10 +5902,10 @@ namespace Microsoft.Dafny if (firstEffectfulRhs == null) { if (update.Lhss.Count == 0) { Contract.Assert(update.Rhss.Count == 1); // guaranteed by the parser - Error(update, "expected method call, found expression"); + reporter.Error(MessageSource.Resolver, update, "expected method call, found expression"); } else if (update.Lhss.Count != update.Rhss.Count) { - Error(update, "the number of left-hand sides ({0}) and right-hand sides ({1}) must match for a multi-assignment", update.Lhss.Count, update.Rhss.Count); - } else if (ErrorCount == errorCountBeforeCheckingLhs) { + reporter.Error(MessageSource.Resolver, update, "the number of left-hand sides ({0}) and right-hand sides ({1}) must match for a multi-assignment", update.Lhss.Count, update.Rhss.Count); + } else if (reporter.Count(ErrorLevel.Error) == errorCountBeforeCheckingLhs) { // add the statements here in a sequence, but don't use that sequence later for translation (instead, should translate properly as multi-assignment) for (int i = 0; i < update.Lhss.Count; i++) { var a = new AssignStmt(update.Tok, update.EndTok, update.Lhss[i].Resolved, update.Rhss[i]); @@ -6031,19 +5915,19 @@ namespace Microsoft.Dafny } else if (update.CanMutateKnownState) { if (1 < update.Rhss.Count) { - Error(firstEffectfulRhs, "cannot have effectful parameter in multi-return statement."); + reporter.Error(MessageSource.Resolver, firstEffectfulRhs, "cannot have effectful parameter in multi-return statement."); } else { // it might be ok, if it is a TypeRhs Contract.Assert(update.Rhss.Count == 1); if (methodCallInfo != null) { - Error(methodCallInfo.Tok, "cannot have method call in return statement."); + reporter.Error(MessageSource.Resolver, methodCallInfo.Tok, "cannot have method call in return statement."); } else { // we have a TypeRhs Contract.Assert(update.Rhss[0] is TypeRhs); var tr = (TypeRhs)update.Rhss[0]; Contract.Assert(tr.InitCall != null); // there were effects, so this must have been a call. if (tr.CanAffectPreviouslyKnownExpressions) { - Error(tr.Tok, "can only have initialization methods which modify at most 'this'."); - } else if (ErrorCount == errorCountBeforeCheckingLhs) { + reporter.Error(MessageSource.Resolver, tr.Tok, "can only have initialization methods which modify at most 'this'."); + } else if (reporter.Count(ErrorLevel.Error) == errorCountBeforeCheckingLhs) { var a = new AssignStmt(update.Tok, update.EndTok, update.Lhss[0].Resolved, tr); update.ResolvedStatements.Add(a); } @@ -6053,17 +5937,17 @@ namespace Microsoft.Dafny } else { // if there was an effectful RHS, that must be the only RHS if (update.Rhss.Count != 1) { - Error(firstEffectfulRhs, "an update statement is allowed an effectful RHS only if there is just one RHS"); + reporter.Error(MessageSource.Resolver, firstEffectfulRhs, "an update statement is allowed an effectful RHS only if there is just one RHS"); } else if (methodCallInfo == null) { // must be a single TypeRhs if (update.Lhss.Count != 1) { Contract.Assert(2 <= update.Lhss.Count); // the parser allows 0 Lhss only if the whole statement looks like an expression (not a TypeRhs) - Error(update.Lhss[1].tok, "the number of left-hand sides ({0}) and right-hand sides ({1}) must match for a multi-assignment", update.Lhss.Count, update.Rhss.Count); - } else if (ErrorCount == errorCountBeforeCheckingLhs) { + reporter.Error(MessageSource.Resolver, update.Lhss[1].tok, "the number of left-hand sides ({0}) and right-hand sides ({1}) must match for a multi-assignment", update.Lhss.Count, update.Rhss.Count); + } else if (reporter.Count(ErrorLevel.Error) == errorCountBeforeCheckingLhs) { var a = new AssignStmt(update.Tok, update.EndTok, update.Lhss[0].Resolved, update.Rhss[0]); update.ResolvedStatements.Add(a); } - } else if (ErrorCount == errorCountBeforeCheckingLhs) { + } else if (reporter.Count(ErrorLevel.Error) == errorCountBeforeCheckingLhs) { // a call statement var resolvedLhss = new List(); foreach (var ll in update.Lhss) { @@ -6090,7 +5974,7 @@ namespace Microsoft.Dafny foreach (var lhs in s.Lhss) { var ide = lhs.Resolved as IdentifierExpr; if (ide == null) { - Error(lhs, "the assign-such-that statement currently only supports local-variable LHSs"); + reporter.Error(MessageSource.Resolver, lhs, "the assign-such-that statement currently only supports local-variable LHSs"); } else { varLhss.Add(ide.Var); } @@ -6098,17 +5982,17 @@ namespace Microsoft.Dafny } s.IsGhost = s.Lhss.TrueForAll(AssignStmt.LhsIsToGhost); - var ec = ErrorCount; + var ec = reporter.Count(ErrorLevel.Error); ResolveExpression(s.Expr, new ResolveOpts(codeContext, true, specContextOnly)); if (!UnifyTypes(s.Expr.Type, Type.Bool)) { - Error(s.Expr, "type of RHS of assign-such-that statement must be boolean (got {0})", s.Expr.Type); + reporter.Error(MessageSource.Resolver, s.Expr, "type of RHS of assign-such-that statement must be boolean (got {0})", s.Expr.Type); } - if (ec == ErrorCount && !s.IsGhost && s.AssumeToken == null && !specContextOnly) { + if (ec == reporter.Count(ErrorLevel.Error) && !s.IsGhost && s.AssumeToken == null && !specContextOnly) { CheckIsNonGhost(s.Expr); var missingBounds = new List(); CheckTypeInference(s.Expr); // we need to resolve operators before the call to DiscoverBoundsAux - var allBounds = DiscoverBoundsAux(s.Tok, varLhss, s.Expr, true, true, true, missingBounds); + var allBounds = DiscoverBoundsAux(s.Tok, varLhss, s.Expr, true, true, true, missingBounds, reporter); if (missingBounds.Count != 0) { s.MissingBounds = missingBounds; // so that an error message can be produced during compilation } else { @@ -6130,12 +6014,12 @@ namespace Microsoft.Dafny bool isGhost = specContextOnly; // first, resolve the guards, which tells us whether or not the entire statement is a ghost statement foreach (var alternative in alternatives) { - int prevErrorCount = ErrorCount; + int prevErrorCount = reporter.Count(ErrorLevel.Error); ResolveExpression(alternative.Guard, new ResolveOpts(codeContext, true, specContextOnly)); Contract.Assert(alternative.Guard.Type != null); // follows from postcondition of ResolveExpression - bool successfullyResolved = ErrorCount == prevErrorCount; + bool successfullyResolved = reporter.Count(ErrorLevel.Error) == prevErrorCount; if (!UnifyTypes(alternative.Guard.Type, Type.Bool)) { - Error(alternative.Guard, "condition is expected to be of type {0}, but is {1}", Type.Bool, alternative.Guard.Type); + reporter.Error(MessageSource.Resolver, alternative.Guard, "condition is expected to be of type {0}, but is {1}", Type.Bool, alternative.Guard.Type); } if (!specContextOnly && successfullyResolved) { isGhost = isGhost || UsesSpecFeatures(alternative.Guard); @@ -6174,11 +6058,11 @@ namespace Microsoft.Dafny var callee = s.Method; Contract.Assert(callee != null); // follows from the invariant of CallStmt if (!isInitCall && callee is Constructor) { - Error(s, "a constructor is allowed to be called only when an object is being allocated"); + reporter.Error(MessageSource.Resolver, s, "a constructor is allowed to be called only when an object is being allocated"); } s.IsGhost = callee.IsGhost; if (specContextOnly && !callee.IsGhost) { - Error(s, "only ghost methods can be called from this context"); + reporter.Error(MessageSource.Resolver, s, "only ghost methods can be called from this context"); } // resolve left-hand sides @@ -6192,49 +6076,49 @@ namespace Microsoft.Dafny int j = 0; foreach (Expression e in s.Args) { bool allowGhost = s.IsGhost || callee.Ins.Count <= j || callee.Ins[j].IsGhost; - var ec = ErrorCount; + var ec = reporter.Count(ErrorLevel.Error); ResolveExpression(e, new ResolveOpts(codeContext, true, allowGhost)); - if (ec == ErrorCount && !allowGhost) { + if (ec == reporter.Count(ErrorLevel.Error) && !allowGhost) { CheckIsNonGhost(e); } j++; } if (callee.Ins.Count != s.Args.Count) { - Error(s, "wrong number of method arguments (got {0}, expected {1})", s.Args.Count, callee.Ins.Count); + reporter.Error(MessageSource.Resolver, s, "wrong number of method arguments (got {0}, expected {1})", s.Args.Count, callee.Ins.Count); } else if (callee.Outs.Count != s.Lhs.Count) { if (isInitCall) { - Error(s, "a method called as an initialization method must not have any result arguments"); + reporter.Error(MessageSource.Resolver, s, "a method called as an initialization method must not have any result arguments"); } else { - Error(s, "wrong number of method result arguments (got {0}, expected {1})", s.Lhs.Count, callee.Outs.Count); + reporter.Error(MessageSource.Resolver, s, "wrong number of method result arguments (got {0}, expected {1})", s.Lhs.Count, callee.Outs.Count); } } else { if (isInitCall) { if (callee.IsStatic) { - Error(s.Tok, "a method called as an initialization method must not be 'static'"); + reporter.Error(MessageSource.Resolver, s.Tok, "a method called as an initialization method must not be 'static'"); } } else if (!callee.IsStatic) { if (!scope.AllowInstance && s.Receiver is ThisExpr) { // The call really needs an instance, but that instance is given as 'this', which is not // available in this context. For more details, see comment in the resolution of a // FunctionCallExpr. - Error(s.Receiver, "'this' is not allowed in a 'static' context"); + reporter.Error(MessageSource.Resolver, s.Receiver, "'this' is not allowed in a 'static' context"); } else if (s.Receiver is StaticReceiverExpr) { - Error(s.Receiver, "call to instance method requires an instance"); + reporter.Error(MessageSource.Resolver, s.Receiver, "call to instance method requires an instance"); } } // type check the arguments for (int i = 0; i < callee.Ins.Count; i++) { Type st = SubstType(callee.Ins[i].Type, s.MethodSelect.TypeArgumentSubstitutions()); if (!UnifyTypes(cce.NonNull(s.Args[i].Type), st)) { - Error(s, "incorrect type of method in-parameter {0} (expected {1}, got {2})", i, st, s.Args[i].Type); + reporter.Error(MessageSource.Resolver, s, "incorrect type of method in-parameter {0} (expected {1}, got {2})", i, st, s.Args[i].Type); } } for (int i = 0; i < callee.Outs.Count; i++) { Type st = SubstType(callee.Outs[i].Type, s.MethodSelect.TypeArgumentSubstitutions()); var lhs = s.Lhs[i]; if (!UnifyTypes(cce.NonNull(lhs.Type), st)) { - Error(s, "incorrect type of method out-parameter {0} (expected {1}, got {2})", i, st, lhs.Type); + reporter.Error(MessageSource.Resolver, s, "incorrect type of method out-parameter {0} (expected {1}, got {2})", i, st, lhs.Type); } else { var resolvedLhs = lhs.Resolved; if (!specContextOnly && (s.IsGhost || callee.Outs[i].IsGhost)) { @@ -6246,17 +6130,17 @@ namespace Microsoft.Dafny // the variable was actually declared in this statement, so auto-declare it as ghost ((LocalVariable)ll.Var).MakeGhost(); } else { - Error(s, "actual out-parameter {0} is required to be a ghost variable", i); + reporter.Error(MessageSource.Resolver, s, "actual out-parameter {0} is required to be a ghost variable", i); } } } else if (resolvedLhs is MemberSelectExpr) { var ll = (MemberSelectExpr)resolvedLhs; if (!ll.Member.IsGhost) { - Error(s, "actual out-parameter {0} is required to be a ghost field", i); + reporter.Error(MessageSource.Resolver, s, "actual out-parameter {0} is required to be a ghost field", i); } } else { // this is an array update, and arrays are always non-ghost - Error(s, "actual out-parameter {0} is required to be a ghost variable", i); + reporter.Error(MessageSource.Resolver, s, "actual out-parameter {0} is required to be a ghost variable", i); } } // LHS must denote a mutable field. @@ -6283,7 +6167,7 @@ namespace Microsoft.Dafny } } if (Contract.Exists(callee.Decreases.Expressions, e => e is WildcardExpr) && !codeContext.AllowsNontermination) { - Error(s.Tok, "a call to a possibly non-terminating method is allowed only if the calling method is also declared (with 'decreases *') to be possibly non-terminating"); + reporter.Error(MessageSource.Resolver, s.Tok, "a call to a possibly non-terminating method is allowed only if the calling method is also declared (with 'decreases *') to be possibly non-terminating"); } } @@ -6298,26 +6182,26 @@ namespace Microsoft.Dafny if (lhs is IdentifierExpr) { var ll = (IdentifierExpr)lhs; if (!ll.Var.IsMutable) { - Error(lhs, "LHS of assignment must denote a mutable variable"); + reporter.Error(MessageSource.Resolver, lhs, "LHS of assignment must denote a mutable variable"); } } else if (lhs is MemberSelectExpr) { var ll = (MemberSelectExpr)lhs; var field = ll.Member as Field; if (field == null || !field.IsUserMutable) { - Error(lhs, "LHS of assignment must denote a mutable field"); + reporter.Error(MessageSource.Resolver, lhs, "LHS of assignment must denote a mutable field"); } } else if (lhs is SeqSelectExpr) { var ll = (SeqSelectExpr)lhs; if (!UnifyTypes(ll.Seq.Type, ResolvedArrayType(ll.Seq.tok, 1, new InferredTypeProxy(), codeContext))) { - Error(ll.Seq, "LHS of array assignment must denote an array element (found {0})", ll.Seq.Type); + reporter.Error(MessageSource.Resolver, ll.Seq, "LHS of array assignment must denote an array element (found {0})", ll.Seq.Type); } if (!ll.SelectOne) { - Error(ll.Seq, "cannot assign to a range of array elements (try the 'forall' statement)"); + reporter.Error(MessageSource.Resolver, ll.Seq, "cannot assign to a range of array elements (try the 'forall' statement)"); } } else if (lhs is MultiSelectExpr) { // nothing to check; this can only denote an array element } else { - Error(lhs, "LHS of assignment must denote a mutable variable or field"); + reporter.Error(MessageSource.Resolver, lhs, "LHS of assignment must denote a mutable variable or field"); } } @@ -6333,9 +6217,9 @@ namespace Microsoft.Dafny Contract.Assert(lnode.Name != null); // LabelNode's with .Label==null are added only during resolution of the break statements with 'stmt' as their target, which hasn't happened yet var prev = labeledStatements.Find(lnode.Name); if (prev == ss) { - Error(lnode.Tok, "duplicate label"); + reporter.Error(MessageSource.Resolver, lnode.Tok, "duplicate label"); } else if (prev != null) { - Error(lnode.Tok, "label shadows an enclosing label"); + reporter.Error(MessageSource.Resolver, lnode.Tok, "label shadows an enclosing label"); } else { var r = labeledStatements.Push(lnode.Name, ss); Contract.Assert(r == Scope.PushResult.Success); // since we just checked for duplicates, we expect the Push to succeed @@ -6357,13 +6241,13 @@ namespace Microsoft.Dafny if (stmt is PredicateStmt) { // cool } else if (stmt is PrintStmt) { - Error(stmt, "print statement is not allowed inside a forall statement"); + reporter.Error(MessageSource.Resolver, stmt, "print statement is not allowed inside a forall statement"); } else if (stmt is BreakStmt) { // this case is checked already in the first pass through the forall-statement body, by doing so from an empty set of labeled statements and resetting the loop-stack } else if (stmt is ReturnStmt) { - Error(stmt, "return statement is not allowed inside a forall statement"); + reporter.Error(MessageSource.Resolver, stmt, "return statement is not allowed inside a forall statement"); } else if (stmt is YieldStmt) { - Error(stmt, "yield statement is not allowed inside a forall statement"); + reporter.Error(MessageSource.Resolver, stmt, "yield statement is not allowed inside a forall statement"); } else if (stmt is AssignSuchThatStmt) { var s = (AssignSuchThatStmt)stmt; foreach (var lhs in s.Lhss) { @@ -6385,9 +6269,9 @@ namespace Microsoft.Dafny var rhs = s.Rhs; // ExprRhs and HavocRhs are fine, but TypeRhs is not if (rhs is TypeRhs) { if (kind == ForallStmt.ParBodyKind.Assign) { - Error(rhs.Tok, "new allocation not supported in forall statements"); + reporter.Error(MessageSource.Resolver, rhs.Tok, "new allocation not supported in forall statements"); } else { - Error(rhs.Tok, "new allocation not allowed in ghost context"); + reporter.Error(MessageSource.Resolver, rhs.Tok, "new allocation not allowed in ghost context"); } } } else if (stmt is CallStmt) { @@ -6396,14 +6280,14 @@ namespace Microsoft.Dafny var idExpr = lhs as IdentifierExpr; if (idExpr != null) { if (scope.ContainsDecl(idExpr.Var)) { - Error(stmt, "body of forall statement is attempting to update a variable declared outside the forall statement"); + reporter.Error(MessageSource.Resolver, stmt, "body of forall statement is attempting to update a variable declared outside the forall statement"); } } else { - Error(stmt, "the body of the enclosing forall statement is not allowed to update heap locations"); + reporter.Error(MessageSource.Resolver, stmt, "the body of the enclosing forall statement is not allowed to update heap locations"); } } if (s.Method.Mod.Expressions.Count != 0) { - Error(stmt, "the body of the enclosing forall statement is not allowed to update heap locations, so any call must be to a method with an empty modifies clause"); + reporter.Error(MessageSource.Resolver, stmt, "the body of the enclosing forall statement is not allowed to update heap locations, so any call must be to a method with an empty modifies clause"); } if (!s.Method.IsGhost) { // The reason for this restriction is that the compiler is going to omit the forall statement altogether--it has @@ -6411,7 +6295,7 @@ namespace Microsoft.Dafny // a method that prints something, all calls to non-ghost methods are disallowed. (Note, if this restriction // is somehow lifted in the future, then it is still necessary to enforce s.Method.Mod.Expressions.Count != 0 for // calls to non-ghost methods.) - Error(s, "the body of the enclosing forall statement is not allowed to call non-ghost methods"); + reporter.Error(MessageSource.Resolver, s, "the body of the enclosing forall statement is not allowed to call non-ghost methods"); } } else if (stmt is BlockStmt) { @@ -6455,7 +6339,7 @@ namespace Microsoft.Dafny var s = (ForallStmt)stmt; switch (s.Kind) { case ForallStmt.ParBodyKind.Assign: - Error(stmt, "a forall statement with heap updates is not allowed inside the body of another forall statement"); + reporter.Error(MessageSource.Resolver, stmt, "a forall statement with heap updates is not allowed inside the body of another forall statement"); break; case ForallStmt.ParBodyKind.Call: case ForallStmt.ParBodyKind.Proof: @@ -6486,10 +6370,10 @@ namespace Microsoft.Dafny var idExpr = lhs as IdentifierExpr; if (idExpr != null) { if (scope.ContainsDecl(idExpr.Var)) { - Error(tok, "body of forall statement is attempting to update a variable declared outside the forall statement"); + reporter.Error(MessageSource.Resolver, tok, "body of forall statement is attempting to update a variable declared outside the forall statement"); } } else if (kind != ForallStmt.ParBodyKind.Assign) { - Error(tok, "the body of the enclosing forall statement is not allowed to update heap locations"); + reporter.Error(MessageSource.Resolver, tok, "the body of the enclosing forall statement is not allowed to update heap locations"); } } @@ -6506,9 +6390,9 @@ namespace Microsoft.Dafny } else if (stmt is BreakStmt) { // already checked while resolving hints } else if (stmt is ReturnStmt) { - Error(stmt, "return statement is not allowed inside a hint"); + reporter.Error(MessageSource.Resolver, stmt, "return statement is not allowed inside a hint"); } else if (stmt is YieldStmt) { - Error(stmt, "yield statement is not allowed inside a hint"); + reporter.Error(MessageSource.Resolver, stmt, "yield statement is not allowed inside a hint"); } else if (stmt is AssignSuchThatStmt) { var s = (AssignSuchThatStmt)stmt; foreach (var lhs in s.Lhss) { @@ -6520,7 +6404,7 @@ namespace Microsoft.Dafny } else if (stmt is CallStmt) { var s = (CallStmt)stmt; if (s.Method.Mod.Expressions.Count != 0) { - Error(stmt, "calls to methods with side-effects are not allowed inside a hint"); + reporter.Error(MessageSource.Resolver, stmt, "calls to methods with side-effects are not allowed inside a hint"); } } else if (stmt is UpdateStmt) { var s = (UpdateStmt)stmt; @@ -6558,7 +6442,7 @@ namespace Microsoft.Dafny } else if (stmt is WhileStmt) { var s = (WhileStmt)stmt; if (s.Mod.Expressions != null && s.Mod.Expressions.Count != 0) { - Error(s.Mod.Expressions[0].tok, "a while statement used inside a hint is not allowed to have a modifies clause"); + reporter.Error(MessageSource.Resolver, s.Mod.Expressions[0].tok, "a while statement used inside a hint is not allowed to have a modifies clause"); } if (s.Body != null) { CheckHintRestrictions(s.Body); @@ -6576,7 +6460,7 @@ namespace Microsoft.Dafny var s = (ForallStmt)stmt; switch (s.Kind) { case ForallStmt.ParBodyKind.Assign: - Error(stmt, "a forall statement with heap updates is not allowed inside a hint"); + reporter.Error(MessageSource.Resolver, stmt, "a forall statement with heap updates is not allowed inside a hint"); break; case ForallStmt.ParBodyKind.Call: case ForallStmt.ParBodyKind.Proof: @@ -6609,9 +6493,9 @@ namespace Microsoft.Dafny void CheckHintLhs(IToken tok, Expression lhs) { var idExpr = lhs as IdentifierExpr; if (idExpr == null) { - Error(tok, "a hint is not allowed to update heap locations"); + reporter.Error(MessageSource.Resolver, tok, "a hint is not allowed to update heap locations"); } else if (scope.ContainsDecl(idExpr.Var)) { - Error(tok, "a hint is not allowed to update a variable declared outside the hint"); + reporter.Error(MessageSource.Resolver, tok, "a hint is not allowed to update a variable declared outside the hint"); } } @@ -6623,7 +6507,7 @@ namespace Microsoft.Dafny // "new" is not allowed in ghost contexts if (specContextOnly) { - Error(rr.Tok, "'new' is not allowed in ghost contexts"); + reporter.Error(MessageSource.Resolver, rr.Tok, "'new' is not allowed in ghost contexts"); } if (rr.Type == null) { if (rr.ArrayDimensions != null) { @@ -6635,7 +6519,7 @@ namespace Microsoft.Dafny Contract.Assert(dim != null); ResolveExpression(dim, new ResolveOpts(codeContext, true)); if (!UnifyTypes(dim.Type, new OperationTypeProxy(true, false, false, false, false, false))) { - Error(stmt, "new must use an integer-based expression for the array size (got {0} for index {1})", dim.Type, i); + reporter.Error(MessageSource.Resolver, stmt, "new must use an integer-based expression for the array size (got {0} for index {1})", dim.Type, i); } i++; } @@ -6645,7 +6529,7 @@ namespace Microsoft.Dafny if (rr.Arguments == null) { ResolveType(stmt.Tok, rr.EType, codeContext, ResolveTypeOptionEnum.InferTypeProxies, null); if (!rr.EType.IsRefType) { - Error(stmt, "new can be applied only to reference types (got {0})", rr.EType); + reporter.Error(MessageSource.Resolver, stmt, "new can be applied only to reference types (got {0})", rr.EType); } } else { string initCallName = null; @@ -6668,18 +6552,18 @@ namespace Microsoft.Dafny initCallTok = rr.Tok; } if (!rr.EType.IsRefType) { - Error(stmt, "new can be applied only to reference types (got {0})", rr.EType); + reporter.Error(MessageSource.Resolver, stmt, "new can be applied only to reference types (got {0})", rr.EType); } else { // ---------- new C.Init(EE) Contract.Assert(initCallName != null); - var prevErrorCount = ErrorCount; + var prevErrorCount = reporter.Count(ErrorLevel.Error); // We want to create a MemberSelectExpr for the initializing method. To do that, we create a throw-away receiver of the appropriate // type, create an dot-suffix expression around this receiver, and then resolve it in the usual way for dot-suffix expressions. var lhs = new ImplicitThisExpr(initCallTok) { Type = rr.EType }; var callLhs = new ExprDotName(initCallTok, lhs, initCallName, ret == null ? null : ret.LastComponent.OptTypeArguments); ResolveDotSuffix(callLhs, true, rr.Arguments, new ResolveOpts(codeContext, true, specContextOnly), true); - if (prevErrorCount == ErrorCount) { + if (prevErrorCount == reporter.Count(ErrorLevel.Error)) { Contract.Assert(callLhs.ResolvedExpression is MemberSelectExpr); // since ResolveApplySuffix succeeded and call.Lhs denotes an expression (not a module or a type) var methodSel = (MemberSelectExpr)callLhs.ResolvedExpression; if (methodSel.Member is Method) { @@ -6689,7 +6573,7 @@ namespace Microsoft.Dafny callsConstructor = true; } } else { - Error(initCallTok, "object initialization must denote an initializing method or constructor ({0})", initCallName); + reporter.Error(MessageSource.Resolver, initCallTok, "object initialization must denote an initializing method or constructor ({0})", initCallName); } } } @@ -6699,10 +6583,10 @@ namespace Microsoft.Dafny if (udt != null) { var cl = (ClassDecl)udt.ResolvedClass; // cast is guaranteed by the call to rr.EType.IsRefType above, together with the "rr.EType is UserDefinedType" test if (cl is TraitDecl) { - Error(stmt, "new cannot be applied to a trait"); + reporter.Error(MessageSource.Resolver, stmt, "new cannot be applied to a trait"); } if (!callsConstructor && cl.HasConstructor) { - Error(stmt, "when allocating an object of type '{0}', one of its constructor methods must be called", cl.Name); + reporter.Error(MessageSource.Resolver, stmt, "when allocating an object of type '{0}', one of its constructor methods must be called", cl.Name); } } } @@ -6731,7 +6615,7 @@ namespace Microsoft.Dafny } } if (receiverType is TypeProxy) { - Error(tok, "type of the receiver is not fully determined at this program point", receiverType); + reporter.Error(MessageSource.Resolver, tok, "type of the receiver is not fully determined at this program point", receiverType); return null; } Contract.Assert(receiverType is NonProxyType); // there are only two kinds of types: proxies and non-proxies @@ -6744,20 +6628,20 @@ namespace Microsoft.Dafny if (!classMembers[cd].TryGetValue(memberName, out member)) { var kind = cd is IteratorDecl ? "iterator" : "class"; if (memberName == "_ctor") { - Error(tok, "{0} {1} does not have an anonymous constructor", kind, ctype.Name); + reporter.Error(MessageSource.Resolver, tok, "{0} {1} does not have an anonymous constructor", kind, ctype.Name); } else { // search the static members of the enclosing module or its imports if (moduleInfo.StaticMembers.TryGetValue(memberName, out member)) { Contract.Assert(member.IsStatic); // moduleInfo.StaticMembers is supposed to contain only static members of the module's implicit class _default if (member is AmbiguousMemberDecl) { var ambiguousMember = (AmbiguousMemberDecl)member; - Error(tok, "The name {0} ambiguously refers to a static member in one of the modules {1} (try qualifying the member name with the module name)", memberName, ambiguousMember.ModuleNames()); + reporter.Error(MessageSource.Resolver, tok, "The name {0} ambiguously refers to a static member in one of the modules {1} (try qualifying the member name with the module name)", memberName, ambiguousMember.ModuleNames()); } else { nptype = GetReceiverType(tok, member); return member; } } else { - Error(tok, "member {0} does not exist in {2} {1}", memberName, ctype.Name, kind); + reporter.Error(MessageSource.Resolver, tok, "member {0} does not exist in {2} {1}", memberName, ctype.Name, kind); } } return null; @@ -6771,7 +6655,7 @@ namespace Microsoft.Dafny if (dtd != null) { MemberDecl member; if (!datatypeMembers[dtd].TryGetValue(memberName, out member)) { - Error(tok, "member {0} does not exist in datatype {1}", memberName, dtd.Name); + reporter.Error(MessageSource.Resolver, tok, "member {0} does not exist in datatype {1}", memberName, dtd.Name); return null; } else { nptype = (UserDefinedType)receiverType; @@ -6797,7 +6681,7 @@ namespace Microsoft.Dafny } } - Error(tok, "type {0} does not have a member {1}", receiverType, memberName); + reporter.Error(MessageSource.Resolver, tok, "type {0} does not have a member {1}", receiverType, memberName); return null; } @@ -7021,10 +6905,10 @@ namespace Microsoft.Dafny } else if (expr is NegationExpression) { var e = (NegationExpression)expr; - var errorCount = ErrorCount; + var errorCount = reporter.Count(ErrorLevel.Error); ResolveExpression(e.E, opts); e.Type = e.E.Type; - if (errorCount != ErrorCount) { + if (errorCount != reporter.Count(ErrorLevel.Error)) { // there were errors resolving the operand; take the quick way out and // just let the (already erronous) subexpression be what the negation expression // will resolve to @@ -7074,7 +6958,7 @@ namespace Microsoft.Dafny } } else if (expr is ThisExpr) { if (!scope.AllowInstance) { - Error(expr, "'this' is not allowed in a 'static' context"); + reporter.Error(MessageSource.Resolver, expr, "'this' is not allowed in a 'static' context"); } if (currentClass != null) { expr.Type = GetThisType(expr.tok, currentClass); // do this regardless of scope.AllowInstance, for better error reporting @@ -7086,19 +6970,19 @@ namespace Microsoft.Dafny if (e.Var != null) { expr.Type = e.Var.Type; } else { - Error(expr, "Identifier does not denote a local variable, parameter, or bound variable: {0}", e.Name); + reporter.Error(MessageSource.Resolver, expr, "Identifier does not denote a local variable, parameter, or bound variable: {0}", e.Name); } } else if (expr is DatatypeValue) { DatatypeValue dtv = (DatatypeValue)expr; TopLevelDecl d; if (!moduleInfo.TopLevels.TryGetValue(dtv.DatatypeName, out d)) { - Error(expr.tok, "Undeclared datatype: {0}", dtv.DatatypeName); + reporter.Error(MessageSource.Resolver, expr.tok, "Undeclared datatype: {0}", dtv.DatatypeName); } else if (d is AmbiguousTopLevelDecl) { var ad = (AmbiguousTopLevelDecl)d; - Error(expr.tok, "The name {0} ambiguously refers to a type in one of the modules {1} (try qualifying the type name with the module name)", dtv.DatatypeName, ad.ModuleNames()); + reporter.Error(MessageSource.Resolver, expr.tok, "The name {0} ambiguously refers to a type in one of the modules {1} (try qualifying the type name with the module name)", dtv.DatatypeName, ad.ModuleNames()); } else if (!(d is DatatypeDecl)) { - Error(expr.tok, "Expected datatype: {0}", dtv.DatatypeName); + reporter.Error(MessageSource.Resolver, expr.tok, "Expected datatype: {0}", dtv.DatatypeName); } else { ResolveDatatypeValue(opts, dtv, (DatatypeDecl)d); } @@ -7110,7 +6994,7 @@ namespace Microsoft.Dafny ResolveExpression(ee, opts); Contract.Assert(ee.Type != null); // follows from postcondition of ResolveExpression if (!UnifyTypes(elementType, ee.Type)) { - Error(ee, "All elements of display must be of the same type (got {0}, but type of previous elements is {1})", ee.Type, elementType); + reporter.Error(MessageSource.Resolver, ee, "All elements of display must be of the same type (got {0}, but type of previous elements is {1})", ee.Type, elementType); } } if (expr is SetDisplayExpr) { @@ -7129,12 +7013,12 @@ namespace Microsoft.Dafny ResolveExpression(p.A, opts); Contract.Assert(p.A.Type != null); // follows from postcondition of ResolveExpression if (!UnifyTypes(domainType, p.A.Type)) { - Error(p.A, "All elements of display must be of the same type (got {0}, but type of previous elements is {1})", p.A.Type, domainType); + reporter.Error(MessageSource.Resolver, p.A, "All elements of display must be of the same type (got {0}, but type of previous elements is {1})", p.A.Type, domainType); } ResolveExpression(p.B, opts); Contract.Assert(p.B.Type != null); // follows from postcondition of ResolveExpression if (!UnifyTypes(rangeType, p.B.Type)) { - Error(p.B, "All elements of display must be of the same type (got {0}, but type of previous elements is {1})", p.B.Type, rangeType); + reporter.Error(MessageSource.Resolver, p.B, "All elements of display must be of the same type (got {0}, but type of previous elements is {1})", p.B.Type, rangeType); } } expr.Type = new MapType(e.Finite, domainType, rangeType); @@ -7142,18 +7026,18 @@ namespace Microsoft.Dafny var e = (NameSegment)expr; ResolveNameSegment(e, true, null, opts, false); if (e.Type is Resolver_IdentifierExpr.ResolverType_Module) { - Error(e.tok, "name of module ({0}) is used as a variable", e.Name); + reporter.Error(MessageSource.Resolver, e.tok, "name of module ({0}) is used as a variable", e.Name); } else if (e.Type is Resolver_IdentifierExpr.ResolverType_Type) { - Error(e.tok, "name of type ({0}) is used as a variable", e.Name); + reporter.Error(MessageSource.Resolver, e.tok, "name of type ({0}) is used as a variable", e.Name); } } else if (expr is ExprDotName) { var e = (ExprDotName)expr; ResolveDotSuffix(e, true, null, opts, false); if (e.Type is Resolver_IdentifierExpr.ResolverType_Module) { - Error(e.tok, "name of module ({0}) is used as a variable", e.SuffixName); + reporter.Error(MessageSource.Resolver, e.tok, "name of module ({0}) is used as a variable", e.SuffixName); } else if (e.Type is Resolver_IdentifierExpr.ResolverType_Type) { - Error(e.tok, "name of type ({0}) is used as a variable", e.SuffixName); + reporter.Error(MessageSource.Resolver, e.tok, "name of type ({0}) is used as a variable", e.SuffixName); } } else if (expr is ApplySuffix) { @@ -7193,7 +7077,7 @@ namespace Microsoft.Dafny var field = (Field)member; e.Member = field; if (e.Obj is StaticReceiverExpr) { - Error(expr, "a field must be selected via an object, not just a class name"); + reporter.Error(MessageSource.Resolver, expr, "a field must be selected via an object, not just a class name"); } var ctype = nptype as UserDefinedType; if (ctype == null) { @@ -7205,7 +7089,7 @@ namespace Microsoft.Dafny e.Type = SubstType(field.Type, subst); } } else { - Error(expr, "member {0} in type {1} does not refer to a field or a function", e.MemberName, nptype); + reporter.Error(MessageSource.Resolver, expr, "member {0} in type {1} does not refer to a field or a function", e.MemberName, nptype); } } else if (expr is SeqSelectExpr) { @@ -7219,7 +7103,7 @@ namespace Microsoft.Dafny Contract.Assert(e.Array.Type != null); // follows from postcondition of ResolveExpression Type elementType = new InferredTypeProxy(); if (!UnifyTypes(e.Array.Type, ResolvedArrayType(e.Array.tok, e.Indices.Count, elementType, opts.codeContext))) { - Error(e.Array, "array selection requires an array{0} (got {1})", e.Indices.Count, e.Array.Type); + reporter.Error(MessageSource.Resolver, e.Array, "array selection requires an array{0} (got {1})", e.Indices.Count, e.Array.Type); } int i = 0; foreach (Expression idx in e.Indices) { @@ -7227,7 +7111,7 @@ namespace Microsoft.Dafny ResolveExpression(idx, opts); Contract.Assert(idx.Type != null); // follows from postcondition of ResolveExpression if (!UnifyTypes(idx.Type, new OperationTypeProxy(true, false, false, false, false, false))) { - Error(idx, "array selection requires integer-based numeric indices (got {0} for index {1})", idx.Type, i); + reporter.Error(MessageSource.Resolver, idx, "array selection requires integer-based numeric indices (got {0} for index {1})", idx.Type, i); } i++; } @@ -7244,42 +7128,42 @@ namespace Microsoft.Dafny ResolveExpression(e.Index, opts); Contract.Assert(e.Index.Type != null); // follows from postcondition of ResolveExpression if (!UnifyTypes(e.Index.Type, Type.Int)) { - Error(e.Index, "sequence update requires integer index (got {0})", e.Index.Type); + reporter.Error(MessageSource.Resolver, e.Index, "sequence update requires integer index (got {0})", e.Index.Type); } ResolveExpression(e.Value, opts); Contract.Assert(e.Value.Type != null); // follows from postcondition of ResolveExpression if (!UnifyTypes(e.Value.Type, elementType)) { - Error(e.Value, "sequence update requires the value to have the element type of the sequence (got {0})", e.Value.Type); + reporter.Error(MessageSource.Resolver, e.Value, "sequence update requires the value to have the element type of the sequence (got {0})", e.Value.Type); } expr.Type = e.Seq.Type; } else if (UnifyTypes(e.Seq.Type, new MapType(true, domainType, rangeType))) { ResolveExpression(e.Index, opts); if (!UnifyTypes(e.Index.Type, domainType)) { - Error(e.Index, "map update requires domain element to be of type {0} (got {1})", domainType, e.Index.Type); + reporter.Error(MessageSource.Resolver, e.Index, "map update requires domain element to be of type {0} (got {1})", domainType, e.Index.Type); } ResolveExpression(e.Value, opts); if (!UnifyTypes(e.Value.Type, rangeType)) { - Error(e.Value, "map update requires the value to have the range type {0} (got {1})", rangeType, e.Value.Type); + reporter.Error(MessageSource.Resolver, e.Value, "map update requires the value to have the range type {0} (got {1})", rangeType, e.Value.Type); } expr.Type = e.Seq.Type; } else if (UnifyTypes(e.Seq.Type, new MapType(false, domainType, rangeType))) { ResolveExpression(e.Index, opts); if (!UnifyTypes(e.Index.Type, domainType)) { - Error(e.Index, "imap update requires domain element to be of type {0} (got {1})", domainType, e.Index.Type); + reporter.Error(MessageSource.Resolver, e.Index, "imap update requires domain element to be of type {0} (got {1})", domainType, e.Index.Type); } ResolveExpression(e.Value, opts); if (!UnifyTypes(e.Value.Type, rangeType)) { - Error(e.Value, "imap update requires the value to have the range type {0} (got {1})", rangeType, e.Value.Type); + reporter.Error(MessageSource.Resolver, e.Value, "imap update requires the value to have the range type {0} (got {1})", rangeType, e.Value.Type); } expr.Type = e.Seq.Type; } else if (UnifyTypes(e.Seq.Type, new MultiSetType(elementType))) { ResolveExpression(e.Index, opts); if (!UnifyTypes(e.Index.Type, elementType)) { - Error(e.Index, "multiset update requires domain element to be of type {0} (got {1})", elementType, e.Index.Type); + reporter.Error(MessageSource.Resolver, e.Index, "multiset update requires domain element to be of type {0} (got {1})", elementType, e.Index.Type); } ResolveExpression(e.Value, opts); if (!UnifyTypes(e.Value.Type, new OperationTypeProxy(true, false, false, false, false, false))) { - Error(e.Value, "multiset update requires integer-based numeric value (got {0})", e.Value.Type); + reporter.Error(MessageSource.Resolver, e.Value, "multiset update requires integer-based numeric value (got {0})", e.Value.Type); } expr.Type = e.Seq.Type; @@ -7297,7 +7181,7 @@ namespace Microsoft.Dafny var ei = (SeqUpdateExpr)eIter; if (!(ei.Index is NameSegment|| (ei.Index is LiteralExpr && ((LiteralExpr)ei.Index).Value is BigInteger))) { - Error(expr, "datatype updates must be to datatype destructors"); + reporter.Error(MessageSource.Resolver, expr, "datatype updates must be to datatype destructors"); } else { string destructor_str = null; @@ -7313,12 +7197,12 @@ namespace Microsoft.Dafny if (IndexToValue.ContainsKey(destructor_str)) { // Don't bother trying to optimize this case; we'd have to drop one of the updates, // which makes resolving the dropped update an annoyance. - Warning(ei.tok, "update to {0} overwritten by another update to {1}", destructor_str, destructor_str); + reporter.Warning(MessageSource.Resolver, ei.tok, "update to {0} overwritten by another update to {1}", destructor_str, destructor_str); break; } MemberDecl member; if (!datatypeMembers[dt].TryGetValue(destructor_str, out member)) { - Error(expr, "member {0} does not exist in datatype {1}", destructor_str, dt.Name); + reporter.Error(MessageSource.Resolver, expr, "member {0} does not exist in datatype {1}", destructor_str, dt.Name); } else { DatatypeDestructor destructor = (DatatypeDestructor)member; if (ctor != null && ctor != destructor.EnclosingCtor) { @@ -7367,7 +7251,7 @@ namespace Microsoft.Dafny expr.Type = e0.Type; } else { - Error(expr, "update requires a sequence, map, or datatype (got {0})", e.Seq.Type); + reporter.Error(MessageSource.Resolver, expr, "update requires a sequence, map, or datatype (got {0})", e.Seq.Type); } } else if (expr is FunctionCallExpr) { @@ -7382,13 +7266,13 @@ namespace Microsoft.Dafny } var fnType = e.Function.Type.AsArrowType; if (fnType == null) { - Error(e.tok, "non-function expression (of type {0}) is called with parameters", e.Function.Type); + reporter.Error(MessageSource.Resolver, e.tok, "non-function expression (of type {0}) is called with parameters", e.Function.Type); } else if (fnType.Arity != e.Args.Count) { - Error(e.tok, "wrong number of arguments to function application (function type '{0}' expects {1}, got {2})", fnType, fnType.Arity, e.Args.Count); + reporter.Error(MessageSource.Resolver, e.tok, "wrong number of arguments to function application (function type '{0}' expects {1}, got {2})", fnType, fnType.Arity, e.Args.Count); } else { for (var i = 0; i < fnType.Arity; i++) { if (!UnifyTypes(fnType.Args[i], e.Args[i].Type)) { - Error(e.Args[i].tok, "type mismatch for argument {0} (function expects {1}, got {2})", i, fnType.Args[i], e.Args[i].Type); + reporter.Error(MessageSource.Resolver, e.Args[i].tok, "type mismatch for argument {0} (function expects {1}, got {2})", i, fnType.Args[i], e.Args[i].Type); } } } @@ -7397,7 +7281,7 @@ namespace Microsoft.Dafny } else if (expr is OldExpr) { OldExpr e = (OldExpr)expr; if (!opts.twoState) { - Error(expr, "old expressions are not allowed in this context"); + reporter.Error(MessageSource.Resolver, expr, "old expressions are not allowed in this context"); } ResolveExpression(e.E, opts); expr.Type = e.E.Type; @@ -7406,7 +7290,7 @@ namespace Microsoft.Dafny MultiSetFormingExpr e = (MultiSetFormingExpr)expr; ResolveExpression(e.E, opts); if (!UnifyTypes(e.E.Type, new SetType(true, new InferredTypeProxy())) && !UnifyTypes(e.E.Type, new SeqType(new InferredTypeProxy()))) { - Error(e.tok, "can only form a multiset from a seq or set."); + reporter.Error(MessageSource.Resolver, e.tok, "can only form a multiset from a seq or set."); } expr.Type = new MultiSetType(e.E.Type.AsCollectionType.Arg); @@ -7417,19 +7301,19 @@ namespace Microsoft.Dafny switch (e.Op) { case UnaryOpExpr.Opcode.Not: if (!UnifyTypes(e.E.Type, Type.Bool)) { - Error(expr, "logical negation expects a boolean argument (instead got {0})", e.E.Type); + reporter.Error(MessageSource.Resolver, expr, "logical negation expects a boolean argument (instead got {0})", e.E.Type); } expr.Type = Type.Bool; break; case UnaryOpExpr.Opcode.Cardinality: if (!UnifyTypes(e.E.Type, new CollectionTypeProxy(new InferredTypeProxy(), false, false))) { - Error(expr, "size operator expects a collection argument (instead got {0})", e.E.Type); + reporter.Error(MessageSource.Resolver, expr, "size operator expects a collection argument (instead got {0})", e.E.Type); } expr.Type = Type.Int; break; case UnaryOpExpr.Opcode.Fresh: if (!opts.twoState) { - Error(expr, "fresh expressions are not allowed in this context"); + reporter.Error(MessageSource.Resolver, expr, "fresh expressions are not allowed in this context"); } // the type of e.E must be either an object or a collection of objects Type t = e.E.Type.NormalizeExpand(); @@ -7444,7 +7328,7 @@ namespace Microsoft.Dafny } else if (t.IsDatatype) { // fine, treat this as the datatype itself. } else { - Error(expr, "the argument of a fresh expression must denote an object or a collection of objects (instead got {0})", e.E.Type); + reporter.Error(MessageSource.Resolver, expr, "the argument of a fresh expression must denote an object or a collection of objects (instead got {0})", e.E.Type); } expr.Type = Type.Bool; break; @@ -7458,14 +7342,14 @@ namespace Microsoft.Dafny ResolveExpression(e.E, opts); if (e.ToType.IsNumericBased(Type.NumericPersuation.Int)) { if (!UnifyTypes(e.E.Type, new OperationTypeProxy(true, true, false, false, false, false))) { - Error(expr, "type conversion to an int-based type is allowed only from numeric types (got {0})", e.E.Type); + reporter.Error(MessageSource.Resolver, expr, "type conversion to an int-based type is allowed only from numeric types (got {0})", e.E.Type); } } else if (e.ToType.IsNumericBased(Type.NumericPersuation.Real)) { if (!UnifyTypes(e.E.Type, new OperationTypeProxy(true, true, false, false, false, false))) { - Error(expr, "type conversion to a real-based type is allowed only from numeric types (got {0})", e.E.Type); + reporter.Error(MessageSource.Resolver, expr, "type conversion to a real-based type is allowed only from numeric types (got {0})", e.E.Type); } } else { - Error(expr, "type conversions are not supported to this type (got {0})", e.ToType); + reporter.Error(MessageSource.Resolver, expr, "type conversions are not supported to this type (got {0})", e.ToType); } e.Type = e.ToType; @@ -7482,10 +7366,10 @@ namespace Microsoft.Dafny case BinaryExpr.Opcode.And: case BinaryExpr.Opcode.Or: if (!UnifyTypes(e.E0.Type, Type.Bool)) { - Error(expr, "first argument to {0} must be of type bool (instead got {1})", BinaryExpr.OpcodeString(e.Op), e.E0.Type); + reporter.Error(MessageSource.Resolver, expr, "first argument to {0} must be of type bool (instead got {1})", BinaryExpr.OpcodeString(e.Op), e.E0.Type); } if (!UnifyTypes(e.E1.Type, Type.Bool)) { - Error(expr, "second argument to {0} must be of type bool (instead got {1})", BinaryExpr.OpcodeString(e.Op), e.E1.Type); + reporter.Error(MessageSource.Resolver, expr, "second argument to {0} must be of type bool (instead got {1})", BinaryExpr.OpcodeString(e.Op), e.E1.Type); } expr.Type = Type.Bool; break; @@ -7506,7 +7390,7 @@ namespace Microsoft.Dafny // unification will succeed. } else { // The types are not comparable and do not unify. It's time for an error message. - Error(expr, "arguments must have the same type (got {0} and {1})", e.E0.Type, e.E1.Type); + reporter.Error(MessageSource.Resolver, expr, "arguments must have the same type (got {0} and {1})", e.E0.Type, e.E1.Type); } expr.Type = Type.Bool; break; @@ -7514,12 +7398,12 @@ namespace Microsoft.Dafny case BinaryExpr.Opcode.Disjoint: // TODO: the error messages are backwards from what (ideally) they should be. this is necessary because UnifyTypes can't backtrack. if (!UnifyTypes(e.E0.Type, e.E1.Type)) { - Error(expr, "arguments must have the same type (got {0} and {1})", e.E0.Type, e.E1.Type); + reporter.Error(MessageSource.Resolver, expr, "arguments must have the same type (got {0} and {1})", e.E0.Type, e.E1.Type); } if (!UnifyTypes(e.E0.Type, new SetType(true, new InferredTypeProxy())) && !UnifyTypes(e.E0.Type, new MultiSetType(new InferredTypeProxy())) && !UnifyTypes(e.E0.Type, new MapType(true, new InferredTypeProxy(), new InferredTypeProxy()))) { - Error(expr, "arguments must be of a [multi]set or map type (got {0})", e.E0.Type); + reporter.Error(MessageSource.Resolver, expr, "arguments must be of a [multi]set or map type (got {0})", e.E0.Type); } expr.Type = Type.Bool; break; @@ -7531,26 +7415,26 @@ namespace Microsoft.Dafny if (UnifyTypes(e.E1.Type, new DatatypeProxy(false, false))) { e.ResolvedOp = BinaryExpr.ResolvedOpcode.RankLt; } else { - Error(expr, "arguments to rank comparison must be datatypes (instead of {0})", e.E1.Type); + reporter.Error(MessageSource.Resolver, expr, "arguments to rank comparison must be datatypes (instead of {0})", e.E1.Type); } expr.Type = Type.Bool; } else if (e.Op == BinaryExpr.Opcode.Lt && e.E1.Type.NormalizeExpand().IsIndDatatype) { if (UnifyTypes(e.E0.Type, new DatatypeProxy(false, true))) { e.ResolvedOp = BinaryExpr.ResolvedOpcode.RankLt; } else { - Error(expr, "arguments to rank comparison must be datatypes (instead of {0})", e.E0.Type); + reporter.Error(MessageSource.Resolver, expr, "arguments to rank comparison must be datatypes (instead of {0})", e.E0.Type); } expr.Type = Type.Bool; } else { bool err = false; bool isComparison = e.Op != BinaryExpr.Opcode.Add; if (!UnifyTypes(e.E0.Type, new OperationTypeProxy(true, true, isComparison, true, true, true))) { - Error(expr, "arguments to {0} must be of a numeric type{2} or a collection type (instead got {1})", BinaryExpr.OpcodeString(e.Op), e.E0.Type, + reporter.Error(MessageSource.Resolver, expr, "arguments to {0} must be of a numeric type{2} or a collection type (instead got {1})", BinaryExpr.OpcodeString(e.Op), e.E0.Type, isComparison ? ", char," : ""); err = true; } if (!UnifyTypes(e.E1.Type, e.E0.Type)) { - Error(expr, "arguments to {0} must have the same type (got {1} and {2})", BinaryExpr.OpcodeString(e.Op), e.E0.Type, e.E1.Type); + reporter.Error(MessageSource.Resolver, expr, "arguments to {0} must have the same type (got {1} and {2})", BinaryExpr.OpcodeString(e.Op), e.E0.Type, e.E1.Type); err = true; } if (isComparison) { @@ -7570,26 +7454,26 @@ namespace Microsoft.Dafny if (UnifyTypes(e.E1.Type, new DatatypeProxy(false, true))) { e.ResolvedOp = BinaryExpr.ResolvedOpcode.RankGt; } else { - Error(expr, "arguments to rank comparison must be datatypes (instead of {0})", e.E1.Type); + reporter.Error(MessageSource.Resolver, expr, "arguments to rank comparison must be datatypes (instead of {0})", e.E1.Type); } expr.Type = Type.Bool; } else if (e.Op == BinaryExpr.Opcode.Gt && (e.E1.Type.NormalizeExpand().IsIndDatatype || e.E1.Type.IsTypeParameter)) { if (UnifyTypes(e.E0.Type, new DatatypeProxy(false, false))) { e.ResolvedOp = BinaryExpr.ResolvedOpcode.RankGt; } else { - Error(expr, "arguments to rank comparison must be datatypes (instead of {0})", e.E0.Type); + reporter.Error(MessageSource.Resolver, expr, "arguments to rank comparison must be datatypes (instead of {0})", e.E0.Type); } expr.Type = Type.Bool; } else { bool err = false; bool isComparison = e.Op == BinaryExpr.Opcode.Gt || e.Op == BinaryExpr.Opcode.Ge; if (!UnifyTypes(e.E0.Type, new OperationTypeProxy(true, true, isComparison, false, true, true))) { - Error(expr, "arguments to {0} must be of a numeric type{2} or a set type (instead got {1})", BinaryExpr.OpcodeString(e.Op), e.E0.Type, + reporter.Error(MessageSource.Resolver, expr, "arguments to {0} must be of a numeric type{2} or a set type (instead got {1})", BinaryExpr.OpcodeString(e.Op), e.E0.Type, isComparison ? ", char, " : ""); err = true; } if (!UnifyTypes(e.E1.Type, e.E0.Type)) { - Error(expr, "arguments to {0} must have the same type (got {1} and {2})", BinaryExpr.OpcodeString(e.Op), e.E0.Type, e.E1.Type); + reporter.Error(MessageSource.Resolver, expr, "arguments to {0} must have the same type (got {1} and {2})", BinaryExpr.OpcodeString(e.Op), e.E0.Type, e.E1.Type); err = true; } if (isComparison) { @@ -7604,27 +7488,27 @@ namespace Microsoft.Dafny case BinaryExpr.Opcode.In: case BinaryExpr.Opcode.NotIn: if (!UnifyTypes(e.E1.Type, new CollectionTypeProxy(e.E0.Type, true, true))) { - Error(expr, "second argument to \"{0}\" must be a set, multiset, or sequence with elements of type {1}, or a map with domain {1} (instead got {2})", BinaryExpr.OpcodeString(e.Op), e.E0.Type, e.E1.Type); + reporter.Error(MessageSource.Resolver, expr, "second argument to \"{0}\" must be a set, multiset, or sequence with elements of type {1}, or a map with domain {1} (instead got {2})", BinaryExpr.OpcodeString(e.Op), e.E0.Type, e.E1.Type); } expr.Type = Type.Bool; break; case BinaryExpr.Opcode.Div: if (!UnifyTypes(e.E0.Type, new OperationTypeProxy(true, true, false, false, false, false))) { - Error(expr, "first argument to {0} must be of numeric type (instead got {1})", BinaryExpr.OpcodeString(e.Op), e.E0.Type); + reporter.Error(MessageSource.Resolver, expr, "first argument to {0} must be of numeric type (instead got {1})", BinaryExpr.OpcodeString(e.Op), e.E0.Type); } if (!UnifyTypes(e.E1.Type, e.E0.Type)) { - Error(expr, "arguments to {0} must have the same type (got {1} and {2})", BinaryExpr.OpcodeString(e.Op), e.E0.Type, e.E1.Type); + reporter.Error(MessageSource.Resolver, expr, "arguments to {0} must have the same type (got {1} and {2})", BinaryExpr.OpcodeString(e.Op), e.E0.Type, e.E1.Type); } expr.Type = e.E0.Type; break; case BinaryExpr.Opcode.Mod: if (!UnifyTypes(e.E0.Type, new OperationTypeProxy(true, false, false, false, false, false))) { - Error(expr, "first argument to {0} must be of type int (instead got {1})", BinaryExpr.OpcodeString(e.Op), e.E0.Type); + reporter.Error(MessageSource.Resolver, expr, "first argument to {0} must be of type int (instead got {1})", BinaryExpr.OpcodeString(e.Op), e.E0.Type); } if (!UnifyTypes(e.E1.Type, e.E0.Type)) { - Error(expr, "second argument to {0} must be of type int (instead got {1})", BinaryExpr.OpcodeString(e.Op), e.E1.Type); + reporter.Error(MessageSource.Resolver, expr, "second argument to {0} must be of type int (instead got {1})", BinaryExpr.OpcodeString(e.Op), e.E1.Type); } expr.Type = e.E0.Type; break; @@ -7644,13 +7528,13 @@ namespace Microsoft.Dafny case TernaryExpr.Opcode.PrefixEqOp: case TernaryExpr.Opcode.PrefixNeqOp: if (!UnifyTypes(e.E0.Type, Type.Int)) { - Error(e.E0, "prefix-equality limit argument must be an integer expression (got {0})", e.E0.Type); + reporter.Error(MessageSource.Resolver, e.E0, "prefix-equality limit argument must be an integer expression (got {0})", e.E0.Type); } if (!UnifyTypes(e.E1.Type, new DatatypeProxy(true))) { - Error(expr, "arguments to prefix equality must be codatatypes (instead of {0})", e.E1.Type); + reporter.Error(MessageSource.Resolver, expr, "arguments to prefix equality must be codatatypes (instead of {0})", e.E1.Type); } if (!UnifyTypes(e.E1.Type, e.E2.Type)) { - Error(expr, "arguments must have the same type (got {0} and {1})", e.E1.Type, e.E2.Type); + reporter.Error(MessageSource.Resolver, expr, "arguments must have the same type (got {0} and {1})", e.E1.Type, e.E2.Type); } expr.Type = Type.Bool; break; @@ -7667,7 +7551,7 @@ namespace Microsoft.Dafny } scope.PushMarker(); if (e.LHSs.Count != e.RHSs.Count) { - Error(expr, "let expression must have same number of LHSs (found {0}) as RHSs (found {1})", e.LHSs.Count, e.RHSs.Count); + reporter.Error(MessageSource.Resolver, expr, "let expression must have same number of LHSs (found {0}) as RHSs (found {1})", e.LHSs.Count, e.RHSs.Count); } var i = 0; foreach (var lhs in e.LHSs) { @@ -7681,14 +7565,14 @@ namespace Microsoft.Dafny } if (c == 0) { // Every identifier-looking thing in the pattern resolved to a constructor; that is, this LHS is a constant literal - Error(lhs.tok, "LHS is a constant literal; to be legal, it must introduce at least one bound variable"); + reporter.Error(MessageSource.Resolver, lhs.tok, "LHS is a constant literal; to be legal, it must introduce at least one bound variable"); } i++; } } else { // let-such-that expression if (e.RHSs.Count != 1) { - Error(expr, "let-such-that expression must have just one RHS (found {0})", e.RHSs.Count); + reporter.Error(MessageSource.Resolver, expr, "let-such-that expression must have just one RHS (found {0})", e.RHSs.Count); } // the bound variables are in scope in the RHS of a let-such-that expression scope.PushMarker(); @@ -7701,7 +7585,7 @@ namespace Microsoft.Dafny foreach (var rhs in e.RHSs) { ResolveExpression(rhs, opts); if (!UnifyTypes(rhs.Type, Type.Bool)) { - Error(rhs.tok, "type of RHS of let-such-that expression must be boolean (got {0})", rhs.Type); + reporter.Error(MessageSource.Resolver, rhs.tok, "type of RHS of let-such-that expression must be boolean (got {0})", rhs.Type); } } if (!opts.DontCareAboutCompilation && !e.BoundVars.All(bv => bv.IsGhost)) { @@ -7720,7 +7604,7 @@ namespace Microsoft.Dafny e.Type = e.Body.Type; } else if (expr is QuantifierExpr) { QuantifierExpr e = (QuantifierExpr)expr; - int prevErrorCount = ErrorCount; + int prevErrorCount = reporter.Count(ErrorLevel.Error); bool _val = true; bool typeQuantifier = Attributes.ContainsBool(e.Attributes, "typeQuantifier", ref _val) && _val; allTypeParameters.PushMarker(); @@ -7732,19 +7616,19 @@ namespace Microsoft.Dafny ResolveType(v.tok, v.Type, opts.codeContext, option, typeQuantifier ? e.TypeArgs : null); } if (e.TypeArgs.Count > 0 && !typeQuantifier) { - Error(expr, "a quantifier cannot quantify over types. Possible fix: use the experimental attribute :typeQuantifier"); + reporter.Error(MessageSource.Resolver, expr, "a quantifier cannot quantify over types. Possible fix: use the experimental attribute :typeQuantifier"); } if (e.Range != null) { ResolveExpression(e.Range, new ResolveOpts(opts, true)); Contract.Assert(e.Range.Type != null); // follows from postcondition of ResolveExpression if (!UnifyTypes(e.Range.Type, Type.Bool)) { - Error(expr, "range of quantifier must be of type bool (instead got {0})", e.Range.Type); + reporter.Error(MessageSource.Resolver, expr, "range of quantifier must be of type bool (instead got {0})", e.Range.Type); } } ResolveExpression(e.Term, new ResolveOpts(opts, true)); Contract.Assert(e.Term.Type != null); // follows from postcondition of ResolveExpression if (!UnifyTypes(e.Term.Type, Type.Bool)) { - Error(expr, "body of quantifier must be of type bool (instead got {0})", e.Term.Type); + reporter.Error(MessageSource.Resolver, expr, "body of quantifier must be of type bool (instead got {0})", e.Term.Type); } // Since the body is more likely to infer the types of the bound variables, resolve it // first (above) and only then resolve the attributes (below). @@ -7753,10 +7637,10 @@ namespace Microsoft.Dafny allTypeParameters.PopMarker(); expr.Type = Type.Bool; - if (prevErrorCount == ErrorCount) { + if (prevErrorCount == reporter.Count(ErrorLevel.Error)) { var missingBounds = new List(); CheckTypeInference(e.LogicalBody()); // we need to resolve operators before the call to DiscoverBounds - e.Bounds = DiscoverBounds(e.tok, e.BoundVars, e.LogicalBody(), e is ExistsExpr, false, missingBounds); + e.Bounds = DiscoverBounds(e.tok, e.BoundVars, e.LogicalBody(), e is ExistsExpr, false, missingBounds, reporter); if (missingBounds.Count != 0) { // Report errors here about quantifications that depend on the allocation state. var mb = missingBounds; @@ -7764,7 +7648,7 @@ namespace Microsoft.Dafny mb = new List(); // (who cares if we allocate another array; this happens only in the case of a resolution error anyhow) foreach (var bv in missingBounds) { if (bv.Type.IsRefType) { - Error(expr, "a quantifier involved in a function definition is not allowed to depend on the set of allocated references; Dafny's heuristics can't figure out a bound for the values of '{0}'", bv.Name); + reporter.Error(MessageSource.Resolver, expr, "a quantifier involved in a function definition is not allowed to depend on the set of allocated references; Dafny's heuristics can't figure out a bound for the values of '{0}'", bv.Name); } else { mb.Add(bv); } @@ -7778,7 +7662,7 @@ namespace Microsoft.Dafny } else if (expr is SetComprehension) { var e = (SetComprehension)expr; - int prevErrorCount = ErrorCount; + int prevErrorCount = reporter.Count(ErrorLevel.Error); scope.PushMarker(); foreach (BoundVar v in e.BoundVars) { ScopePushAndReport(scope, v, "bound-variable"); @@ -7787,7 +7671,7 @@ namespace Microsoft.Dafny ResolveExpression(e.Range, opts); Contract.Assert(e.Range.Type != null); // follows from postcondition of ResolveExpression if (!UnifyTypes(e.Range.Type, Type.Bool)) { - Error(expr, "range of comprehension must be of type bool (instead got {0})", e.Range.Type); + reporter.Error(MessageSource.Resolver, expr, "range of comprehension must be of type bool (instead got {0})", e.Range.Type); } ResolveExpression(e.Term, opts); Contract.Assert(e.Term.Type != null); // follows from postcondition of ResolveExpression @@ -7804,10 +7688,10 @@ namespace Microsoft.Dafny } else if (expr is MapComprehension) { var e = (MapComprehension)expr; - int prevErrorCount = ErrorCount; + int prevErrorCount = reporter.Count(ErrorLevel.Error); scope.PushMarker(); if (e.BoundVars.Count != 1) { - Error(e.tok, "a map comprehension must have exactly one bound variable."); + reporter.Error(MessageSource.Resolver, e.tok, "a map comprehension must have exactly one bound variable."); } foreach (BoundVar v in e.BoundVars) { ScopePushAndReport(scope, v, "bound-variable"); @@ -7816,7 +7700,7 @@ namespace Microsoft.Dafny ResolveExpression(e.Range, opts); Contract.Assert(e.Range.Type != null); // follows from postcondition of ResolveExpression if (!UnifyTypes(e.Range.Type, Type.Bool)) { - Error(expr, "range of comprehension must be of type bool (instead got {0})", e.Range.Type); + reporter.Error(MessageSource.Resolver, expr, "range of comprehension must be of type bool (instead got {0})", e.Range.Type); } ResolveExpression(e.Term, opts); Contract.Assert(e.Term.Type != null); // follows from postcondition of ResolveExpression @@ -7825,22 +7709,22 @@ namespace Microsoft.Dafny scope.PopMarker(); expr.Type = new MapType(e.Finite, e.BoundVars[0].Type, e.Term.Type); - if (prevErrorCount == ErrorCount) { + if (prevErrorCount == reporter.Count(ErrorLevel.Error)) { var missingBounds = new List(); CheckTypeInference(e.Range); // we need to resolve operators before the call to DiscoverBounds - e.Bounds = DiscoverBounds(e.tok, e.BoundVars, e.Range, true, false, missingBounds); + e.Bounds = DiscoverBounds(e.tok, e.BoundVars, e.Range, true, false, missingBounds, reporter); if (missingBounds.Count != 0) { e.MissingBounds = missingBounds; if (e.Finite) { foreach (var bv in e.MissingBounds) { - Error(expr, "a map comprehension must produce a finite domain, but Dafny's heuristics can't figure out how to produce a bounded set of values for '{0}'", bv.Name); + reporter.Error(MessageSource.Resolver, expr, "a map comprehension must produce a finite domain, but Dafny's heuristics can't figure out how to produce a bounded set of values for '{0}'", bv.Name); } } } } } else if (expr is LambdaExpr) { var e = (LambdaExpr)expr; - int prevErrorCount = ErrorCount; + int prevErrorCount = reporter.Count(ErrorLevel.Error); scope.PushMarker(); foreach (BoundVar v in e.BoundVars) { ScopePushAndReport(scope, v, "bound-variable"); @@ -7851,7 +7735,7 @@ namespace Microsoft.Dafny ResolveExpression(e.Range, opts); Contract.Assert(e.Range.Type != null); // follows from postcondition of ResolveExpression if (!UnifyTypes(e.Range.Type, Type.Bool)) { - Error(expr, "Precondition must be boolean (got {0})", e.Range.Type); + reporter.Error(MessageSource.Resolver, expr, "Precondition must be boolean (got {0})", e.Range.Type); } } @@ -7867,14 +7751,14 @@ namespace Microsoft.Dafny expr.Type = new SetType(true, new ObjectType()); } else if (expr is StmtExpr) { var e = (StmtExpr)expr; - int prevErrorCount = ErrorCount; + int prevErrorCount = reporter.Count(ErrorLevel.Error); ResolveStatement(e.S, true, opts.codeContext); - if (ErrorCount == prevErrorCount) { + if (reporter.Count(ErrorLevel.Error) == prevErrorCount) { var r = e.S as UpdateStmt; if (r != null && r.ResolvedStatements.Count == 1) { var call = r.ResolvedStatements[0] as CallStmt; if (call.Method.Mod.Expressions.Count != 0) { - Error(call, "calls to methods with side-effects are not allowed inside a statement expression"); + reporter.Error(MessageSource.Resolver, call, "calls to methods with side-effects are not allowed inside a statement expression"); } } } @@ -7891,12 +7775,12 @@ namespace Microsoft.Dafny ResolveExpression(e.Els, opts); Contract.Assert(e.Els.Type != null); // follows from postcondition of ResolveExpression if (!UnifyTypes(e.Test.Type, Type.Bool)) { - Error(expr, "guard condition in if-then-else expression must be a boolean (instead got {0})", e.Test.Type); + reporter.Error(MessageSource.Resolver, expr, "guard condition in if-then-else expression must be a boolean (instead got {0})", e.Test.Type); } if (UnifyTypes(e.Thn.Type, e.Els.Type)) { expr.Type = e.Thn.Type; } else { - Error(expr, "the two branches of an if-then-else expression must have the same type (got {0} and {1})", e.Thn.Type, e.Els.Type); + reporter.Error(MessageSource.Resolver, expr, "the two branches of an if-then-else expression must have the same type (got {0} and {1})", e.Thn.Type, e.Els.Type); } } else if (expr is MatchExpr) { @@ -7926,7 +7810,7 @@ namespace Microsoft.Dafny var subst = new Dictionary(); Dictionary ctors; if (dtd == null) { - Error(me.Source, "the type of the match source expression must be a datatype (instead found {0})", me.Source.Type); + reporter.Error(MessageSource.Resolver, me.Source, "the type of the match source expression must be a datatype (instead found {0})", me.Source.Type); ctors = null; } else { Contract.Assert(sourceType != null); // dtd and sourceType are set together above @@ -7955,15 +7839,15 @@ namespace Microsoft.Dafny if (ctors != null) { Contract.Assert(dtd != null); if (!ctors.TryGetValue(mc.Id, out ctor)) { - Error(mc.tok, "member {0} does not exist in datatype {1}", mc.Id, dtd.Name); + reporter.Error(MessageSource.Resolver, mc.tok, "member {0} does not exist in datatype {1}", mc.Id, dtd.Name); } else { Contract.Assert(ctor != null); // follows from postcondition of TryGetValue mc.Ctor = ctor; if (ctor.Formals.Count != mc.Arguments.Count) { - Error(mc.tok, "member {0} has wrong number of formals (found {1}, expected {2})", mc.Id, mc.Arguments.Count, ctor.Formals.Count); + reporter.Error(MessageSource.Resolver, mc.tok, "member {0} has wrong number of formals (found {1}, expected {2})", mc.Id, mc.Arguments.Count, ctor.Formals.Count); } if (memberNamesUsed.Contains(mc.Id)) { - Error(mc.tok, "member {0} appears in more than one case", mc.Id); + reporter.Error(MessageSource.Resolver, mc.tok, "member {0} appears in more than one case", mc.Id); } else { memberNamesUsed.Add(mc.Id); // add mc.Id to the set of names used } @@ -7979,7 +7863,7 @@ namespace Microsoft.Dafny Formal formal = ctor.Formals[i]; Type st = SubstType(formal.Type, subst); if (!UnifyTypes(v.Type, st)) { - Error(expr, "the declared type of the formal ({0}) does not agree with the corresponding type in the constructor's signature ({1})", v.Type, st); + reporter.Error(MessageSource.Resolver, expr, "the declared type of the formal ({0}) does not agree with the corresponding type in the constructor's signature ({1})", v.Type, st); } v.IsGhost = formal.IsGhost; @@ -8006,7 +7890,7 @@ namespace Microsoft.Dafny Contract.Assert(mc.Body.Type != null); // follows from postcondition of ResolveExpression if (!UnifyTypes(expr.Type, mc.Body.Type)) { - Error(mc.Body.tok, "type of case bodies do not agree (found {0}, previous types {1})", mc.Body.Type, expr.Type); + reporter.Error(MessageSource.Resolver, mc.Body.tok, "type of case bodies do not agree (found {0}, previous types {1})", mc.Body.Type, expr.Type); } scope.PopMarker(); } @@ -8044,13 +7928,13 @@ namespace Microsoft.Dafny if (me.Source is DatatypeValue) { var e = (DatatypeValue)me.Source; if (e.Arguments.Count < 1) { - Error(me.tok, "match source tuple needs at least 1 argument"); + reporter.Error(MessageSource.Resolver, me.tok, "match source tuple needs at least 1 argument"); } else { Expression source = e.Arguments[0]; List cases = new List(); foreach (MatchCaseExpr mc in me.Cases) { if (mc.CasePatterns == null || mc.CasePatterns.Count != e.Arguments.Count) { - Error(mc.tok, "case arguments count does not match source arguments count"); + reporter.Error(MessageSource.Resolver, mc.tok, "case arguments count does not match source arguments count"); } else { CasePattern cp = mc.CasePatterns[0]; List patterns; @@ -8342,17 +8226,17 @@ namespace Microsoft.Dafny var v = pat.Var; ResolveType(v.tok, v.Type, context, ResolveTypeOptionEnum.InferTypeProxies, null); if (!UnifyTypes(v.Type, sourceType)) { - Error(v.tok, "type of corresponding source/RHS ({0}) does not match type of bound variable ({1})", sourceType, v.Type); + reporter.Error(MessageSource.Resolver, v.tok, "type of corresponding source/RHS ({0}) does not match type of bound variable ({1})", sourceType, v.Type); } pat.AssembleExpr(null); } else if (dtd == null) { - Error(pat.tok, "to use a pattern, the type of the source/RHS expression must be a datatype (instead found {0})", sourceType); + reporter.Error(MessageSource.Resolver, pat.tok, "to use a pattern, the type of the source/RHS expression must be a datatype (instead found {0})", sourceType); } else if (ctor == null) { - Error(pat.tok, "constructor {0} does not exist in datatype {1}", pat.Id, dtd.Name); + reporter.Error(MessageSource.Resolver, pat.tok, "constructor {0} does not exist in datatype {1}", pat.Id, dtd.Name); } else { var argCount = pat.Arguments == null ? 0 : pat.Arguments.Count; if (ctor.Formals.Count != argCount) { - Error(pat.tok, "pattern for constructor {0} has wrong number of formals (found {1}, expected {2})", pat.Id, argCount, ctor.Formals.Count); + reporter.Error(MessageSource.Resolver, pat.tok, "pattern for constructor {0} has wrong number of formals (found {1}, expected {2})", pat.Id, argCount, ctor.Formals.Count); } // build the type-parameter substitution map for this use of the datatype Contract.Assert(dtd.TypeArgs.Count == udt.TypeArgs.Count); // follows from the type previously having been successfully resolved @@ -8408,7 +8292,7 @@ namespace Microsoft.Dafny foreach (var ty in expr.OptTypeArguments) { ResolveType(expr.tok, ty, opts.codeContext, ResolveTypeOptionEnum.InferTypeProxies, null); if (ty.IsSubrangeType) { - Error(expr.tok, "sorry, cannot instantiate type parameter with a subrange type"); + reporter.Error(MessageSource.Resolver, expr.tok, "sorry, cannot instantiate type parameter with a subrange type"); } } } @@ -8431,7 +8315,7 @@ namespace Microsoft.Dafny if (v != null) { // ----- 0. local variable, parameter, or bound variable if (expr.OptTypeArguments != null) { - Error(expr.tok, "variable '{0}' does not take any type parameters", expr.Name); + reporter.Error(MessageSource.Resolver, expr.tok, "variable '{0}' does not take any type parameters", expr.Name); } var rr = new IdentifierExpr(expr.tok, expr.Name); rr.Var = v; rr.Type = v.Type; @@ -8443,7 +8327,7 @@ namespace Microsoft.Dafny receiver = new StaticReceiverExpr(expr.tok, (ClassDecl)member.EnclosingClass, true); } else { if (!scope.AllowInstance) { - Error(expr.tok, "'this' is not allowed in a 'static' context"); //FIXME: Rephrase this + reporter.Error(MessageSource.Resolver, expr.tok, "'this' is not allowed in a 'static' context"); //FIXME: Rephrase this // nevertheless, set "receiver" to a value so we can continue resolution } receiver = new ImplicitThisExpr(expr.tok); @@ -8454,10 +8338,10 @@ namespace Microsoft.Dafny // ----- 2. datatype constructor if (pair.Item2) { // there is more than one constructor with this name - Error(expr.tok, "the name '{0}' denotes a datatype constructor, but does not do so uniquely; add an explicit qualification (for example, '{1}.{0}')", expr.Name, pair.Item1.EnclosingDatatype.Name); + reporter.Error(MessageSource.Resolver, expr.tok, "the name '{0}' denotes a datatype constructor, but does not do so uniquely; add an explicit qualification (for example, '{1}.{0}')", expr.Name, pair.Item1.EnclosingDatatype.Name); } else { if (expr.OptTypeArguments != null) { - Error(expr.tok, "datatype constructor does not take any type parameters ('{0}')", expr.Name); + reporter.Error(MessageSource.Resolver, expr.tok, "datatype constructor does not take any type parameters ('{0}')", expr.Name); } var rr = new DatatypeValue(expr.tok, pair.Item1.EnclosingDatatype.Name, expr.Name, args ?? new List()); ResolveDatatypeValue(opts, rr, pair.Item1.EnclosingDatatype); @@ -8472,7 +8356,7 @@ namespace Microsoft.Dafny // ----- 3. Member of the enclosing module if (decl is AmbiguousTopLevelDecl) { var ad = (AmbiguousTopLevelDecl)decl; - Error(expr.tok, "The name {0} ambiguously refers to a type in one of the modules {1} (try qualifying the type name with the module name)", expr.Name, ad.ModuleNames()); + reporter.Error(MessageSource.Resolver, expr.tok, "The name {0} ambiguously refers to a type in one of the modules {1} (try qualifying the type name with the module name)", expr.Name, ad.ModuleNames()); } else { // We have found a module name or a type name, neither of which is an expression. However, the NameSegment we're // looking at may be followed by a further suffix that makes this into an expresion. We postpone the rest of the @@ -8486,7 +8370,7 @@ namespace Microsoft.Dafny Contract.Assert(member.IsStatic); // moduleInfo.StaticMembers is supposed to contain only static members of the module's implicit class _default if (member is AmbiguousMemberDecl) { var ambiguousMember = (AmbiguousMemberDecl)member; - Error(expr.tok, "The name {0} ambiguously refers to a static member in one of the modules {1} (try qualifying the member name with the module name)", expr.Name, ambiguousMember.ModuleNames()); + reporter.Error(MessageSource.Resolver, expr.tok, "The name {0} ambiguously refers to a static member in one of the modules {1} (try qualifying the member name with the module name)", expr.Name, ambiguousMember.ModuleNames()); } else { var receiver = new StaticReceiverExpr(expr.tok, (ClassDecl)member.EnclosingClass, true); r = ResolveExprDotCall(expr.tok, receiver, member, expr.OptTypeArguments, opts.codeContext, allowMethodCall); @@ -8494,7 +8378,7 @@ namespace Microsoft.Dafny } else { // ----- None of the above - Error(expr.tok, "unresolved identifier: {0}", expr.Name); + reporter.Error(MessageSource.Resolver, expr.tok, "unresolved identifier: {0}", expr.Name); } if (r == null) { @@ -8526,7 +8410,7 @@ namespace Microsoft.Dafny foreach (var ty in expr.OptTypeArguments) { ResolveType(expr.tok, ty, opts.codeContext, option, defaultTypeArguments); if (ty.IsSubrangeType) { - Error(expr.tok, "sorry, cannot instantiate type parameter with a subrange type"); + reporter.Error(MessageSource.Resolver, expr.tok, "sorry, cannot instantiate type parameter with a subrange type"); } } } @@ -8550,7 +8434,7 @@ namespace Microsoft.Dafny if (expr.OptTypeArguments == null) { r = new Resolver_IdentifierExpr(expr.tok, tp); } else { - Error(expr.tok, "Type parameter expects no type arguments: {0}", expr.Name); + reporter.Error(MessageSource.Resolver, expr.tok, "Type parameter expects no type arguments: {0}", expr.Name); } #if ASYNC_TASK_TYPES // At the moment, there is no way for a class member to part of a type name, but this changes with async task types } else if (currentClass != null && classMembers.TryGetValue(currentClass, out members) && members.TryGetValue(expr.Name, out member)) { @@ -8572,7 +8456,7 @@ namespace Microsoft.Dafny // ----- 2. Member of the enclosing module if (decl is AmbiguousTopLevelDecl) { var ad = (AmbiguousTopLevelDecl)decl; - Error(expr.tok, "The name {0} ambiguously refers to a type in one of the modules {1} (try qualifying the type name with the module name)", expr.Name, ad.ModuleNames()); + reporter.Error(MessageSource.Resolver, expr.tok, "The name {0} ambiguously refers to a type in one of the modules {1} (try qualifying the type name with the module name)", expr.Name, ad.ModuleNames()); } else { // We have found a module name or a type name, neither of which is a type expression. However, the NameSegment we're // looking at may be followed by a further suffix that makes this into a type expresion. We postpone the rest of the @@ -8594,7 +8478,7 @@ namespace Microsoft.Dafny #endif } else { // ----- None of the above - Error(expr.tok, "Undeclared top-level type or type parameter: {0} (did you forget to qualify a name or declare a module import 'opened?')", expr.Name); + reporter.Error(MessageSource.Resolver, expr.tok, "Undeclared top-level type or type parameter: {0} (did you forget to qualify a name or declare a module import 'opened?')", expr.Name); } if (r == null) { @@ -8615,7 +8499,7 @@ namespace Microsoft.Dafny if (optTypeArguments != null) { // type arguments were supplied; they must be equal in number to those expected if (n != decl.TypeArgs.Count) { - Error(tok, "Wrong number of type arguments ({0} instead of {1}) passed to {2}: {3}", n, decl.TypeArgs.Count, decl.WhatKind, name); + reporter.Error(MessageSource.Resolver, tok, "Wrong number of type arguments ({0} instead of {1}) passed to {2}: {3}", n, decl.TypeArgs.Count, decl.WhatKind, name); } } List tpArgs = new List(); @@ -8667,7 +8551,7 @@ namespace Microsoft.Dafny foreach (var ty in expr.OptTypeArguments) { ResolveType(expr.tok, ty, opts.codeContext, ResolveTypeOptionEnum.InferTypeProxies, null); if (ty.IsSubrangeType) { - Error(expr.tok, "sorry, cannot instantiate type parameter with a subrange type"); + reporter.Error(MessageSource.Resolver, expr.tok, "sorry, cannot instantiate type parameter with a subrange type"); } } } @@ -8690,10 +8574,10 @@ namespace Microsoft.Dafny // ----- 0. datatype constructor if (pair.Item2) { // there is more than one constructor with this name - Error(expr.tok, "the name '{0}' denotes a datatype constructor in module {2}, but does not do so uniquely; add an explicit qualification (for example, '{1}.{0}')", expr.SuffixName, pair.Item1.EnclosingDatatype.Name, ((ModuleDecl)ri.Decl).Name); + reporter.Error(MessageSource.Resolver, expr.tok, "the name '{0}' denotes a datatype constructor in module {2}, but does not do so uniquely; add an explicit qualification (for example, '{1}.{0}')", expr.SuffixName, pair.Item1.EnclosingDatatype.Name, ((ModuleDecl)ri.Decl).Name); } else { if (expr.OptTypeArguments != null) { - Error(expr.tok, "datatype constructor does not take any type parameters ('{0}')", expr.SuffixName); + reporter.Error(MessageSource.Resolver, expr.tok, "datatype constructor does not take any type parameters ('{0}')", expr.SuffixName); } var rr = new DatatypeValue(expr.tok, pair.Item1.EnclosingDatatype.Name, expr.SuffixName, args ?? new List()); ResolveExpression(rr, opts); @@ -8708,7 +8592,7 @@ namespace Microsoft.Dafny // ----- 1. Member of the specified module if (decl is AmbiguousTopLevelDecl) { var ad = (AmbiguousTopLevelDecl)decl; - Error(expr.tok, "The name {0} ambiguously refers to a type in one of the modules {1} (try qualifying the type name with the module name)", expr.SuffixName, ad.ModuleNames()); + reporter.Error(MessageSource.Resolver, expr.tok, "The name {0} ambiguously refers to a type in one of the modules {1} (try qualifying the type name with the module name)", expr.SuffixName, ad.ModuleNames()); } else { // We have found a module name or a type name, neither of which is an expression. However, the ExprDotName we're // looking at may be followed by a further suffix that makes this into an expresion. We postpone the rest of the @@ -8721,13 +8605,13 @@ namespace Microsoft.Dafny Contract.Assert(member.IsStatic); // moduleInfo.StaticMembers is supposed to contain only static members of the module's implicit class _default if (member is AmbiguousMemberDecl) { var ambiguousMember = (AmbiguousMemberDecl)member; - Error(expr.tok, "The name {0} ambiguously refers to a static member in one of the modules {1} (try qualifying the member name with the module name)", expr.SuffixName, ambiguousMember.ModuleNames()); + reporter.Error(MessageSource.Resolver, expr.tok, "The name {0} ambiguously refers to a static member in one of the modules {1} (try qualifying the member name with the module name)", expr.SuffixName, ambiguousMember.ModuleNames()); } else { var receiver = new StaticReceiverExpr(expr.tok, (ClassDecl)member.EnclosingClass, true); r = ResolveExprDotCall(expr.tok, receiver, member, expr.OptTypeArguments, opts.codeContext, allowMethodCall); } } else { - Error(expr.tok, "unresolved identifier: {0}", expr.SuffixName); + reporter.Error(MessageSource.Resolver, expr.tok, "unresolved identifier: {0}", expr.SuffixName); } } else if (lhs != null && lhs.Type is Resolver_IdentifierExpr.ResolverType_Type) { @@ -8746,7 +8630,7 @@ namespace Microsoft.Dafny Dictionary members; if (classMembers.TryGetValue(cd, out members) && members.TryGetValue(expr.SuffixName, out member)) { if (!member.IsStatic) { - Error(expr.tok, "accessing member '{0}' requires an instance expression", expr.SuffixName); //FIXME Unify with similar error message + reporter.Error(MessageSource.Resolver, expr.tok, "accessing member '{0}' requires an instance expression", expr.SuffixName); //FIXME Unify with similar error message // nevertheless, continue creating an expression that approximates a correct one } var receiver = new StaticReceiverExpr(expr.tok, (UserDefinedType)ty.NormalizeExpand(), (ClassDecl)member.EnclosingClass, false); @@ -8759,7 +8643,7 @@ namespace Microsoft.Dafny DatatypeCtor ctor; if (datatypeCtors.TryGetValue(dt, out members) && members.TryGetValue(expr.SuffixName, out ctor)) { if (expr.OptTypeArguments != null) { - Error(expr.tok, "datatype constructor does not take any type parameters ('{0}')", expr.SuffixName); + reporter.Error(MessageSource.Resolver, expr.tok, "datatype constructor does not take any type parameters ('{0}')", expr.SuffixName); } var rr = new DatatypeValue(expr.tok, ctor.EnclosingDatatype.Name, expr.SuffixName, args ?? new List()); ResolveDatatypeValue(opts, rr, ctor.EnclosingDatatype); @@ -8772,7 +8656,7 @@ namespace Microsoft.Dafny } } if (r == null) { - Error(expr.tok, "member '{0}' does not exist in type '{1}'", expr.SuffixName, ri.TypeParamDecl != null ? ri.TypeParamDecl.Name : ri.Decl.Name); + reporter.Error(MessageSource.Resolver, expr.tok, "member '{0}' does not exist in type '{1}'", expr.SuffixName, ri.TypeParamDecl != null ? ri.TypeParamDecl.Name : ri.Decl.Name); } } else if (lhs != null) { // ----- 4. Look up name in the type of the Lhs @@ -8832,7 +8716,7 @@ namespace Microsoft.Dafny foreach (var ty in expr.OptTypeArguments) { ResolveType(expr.tok, ty, opts.codeContext, option, defaultTypeArguments); if (ty.IsSubrangeType) { - Error(expr.tok, "sorry, cannot instantiate type parameter with a subrange type"); + reporter.Error(MessageSource.Resolver, expr.tok, "sorry, cannot instantiate type parameter with a subrange type"); } } } @@ -8851,7 +8735,7 @@ namespace Microsoft.Dafny // ----- 0. Member of the specified module if (decl is AmbiguousTopLevelDecl) { var ad = (AmbiguousTopLevelDecl)decl; - Error(expr.tok, "The name {0} ambiguously refers to a type in one of the modules {1} (try qualifying the type name with the module name)", expr.SuffixName, ad.ModuleNames()); + reporter.Error(MessageSource.Resolver, expr.tok, "The name {0} ambiguously refers to a type in one of the modules {1} (try qualifying the type name with the module name)", expr.SuffixName, ad.ModuleNames()); } else { // We have found a module name or a type name. We create a temporary expression that will never be seen by the compiler // or verifier, just to have a placeholder where we can recorded what we have found. @@ -8869,7 +8753,7 @@ namespace Microsoft.Dafny } #endif } else { - Error(expr.tok, "module '{0}' does not declare a type '{1}'", ri.Decl.Name, expr.SuffixName); + reporter.Error(MessageSource.Resolver, expr.tok, "module '{0}' does not declare a type '{1}'", ri.Decl.Name, expr.SuffixName); } } else if (lhs != null && lhs.Type is Resolver_IdentifierExpr.ResolverType_Type) { @@ -8885,7 +8769,7 @@ namespace Microsoft.Dafny return new ResolveTypeReturn(ty, expr); } if (r == null) { - Error(expr.tok, "member '{0}' does not exist in type '{1}' or cannot be part of type name", expr.SuffixName, ri.TypeParamDecl != null ? ri.TypeParamDecl.Name : ri.Decl.Name); + reporter.Error(MessageSource.Resolver, expr.tok, "member '{0}' does not exist in type '{1}' or cannot be part of type name", expr.SuffixName, ri.TypeParamDecl != null ? ri.TypeParamDecl.Name : ri.Decl.Name); } } @@ -8922,14 +8806,14 @@ namespace Microsoft.Dafny if (member is Field) { if (optTypeArguments != null) { - Error(tok, "a field ({0}) does not take any type arguments (got {1})", member.Name, optTypeArguments.Count); + reporter.Error(MessageSource.Resolver, tok, "a field ({0}) does not take any type arguments (got {1})", member.Name, optTypeArguments.Count); } rr.Type = SubstType(((Field)member).Type, subst); } else if (member is Function) { var fn = (Function)member; int suppliedTypeArguments = optTypeArguments == null ? 0 : optTypeArguments.Count; if (optTypeArguments != null && suppliedTypeArguments != fn.TypeArgs.Count) { - Error(tok, "function '{0}' expects {1} type arguments (got {2})", member.Name, fn.TypeArgs.Count, suppliedTypeArguments); + reporter.Error(MessageSource.Resolver, tok, "function '{0}' expects {1} type arguments (got {2})", member.Name, fn.TypeArgs.Count, suppliedTypeArguments); } rr.TypeApplication = new List(); if (udt != null && udt.ResolvedClass != null) { @@ -8947,11 +8831,11 @@ namespace Microsoft.Dafny var m = (Method)member; if (!allowMethodCall) { // it's a method and method calls are not allowed in the given context - Error(tok, "expression is not allowed to invoke a method ({0})", member.Name); + reporter.Error(MessageSource.Resolver, tok, "expression is not allowed to invoke a method ({0})", member.Name); } int suppliedTypeArguments = optTypeArguments == null ? 0 : optTypeArguments.Count; if (optTypeArguments != null && suppliedTypeArguments != m.TypeArgs.Count) { - Error(tok, "method '{0}' expects {1} type arguments (got {2})", member.Name, m.TypeArgs.Count, suppliedTypeArguments); + reporter.Error(MessageSource.Resolver, tok, "method '{0}' expects {1} type arguments (got {2})", member.Name, m.TypeArgs.Count, suppliedTypeArguments); } rr.TypeApplication = new List(); if (udt != null && udt.ResolvedClass != null) { @@ -8996,7 +8880,7 @@ namespace Microsoft.Dafny Contract.Requires(opts != null); Contract.Ensures(Contract.Result() == null || allowMethodCall); Expression r = null; // upon success, the expression to which the ApplySuffix resolves - var errorCount = ErrorCount; + var errorCount = reporter.Count(ErrorLevel.Error); if (e.Lhs is NameSegment) { r = ResolveNameSegment((NameSegment)e.Lhs, true, e.Args, opts, allowMethodCall); // note, if r is non-null, then e.Args have been resolved and r is a resolved expression that incorporates e.Args @@ -9014,18 +8898,18 @@ namespace Microsoft.Dafny if (fnType == null) { var lhs = e.Lhs.Resolved; if (lhs != null && lhs.Type is Resolver_IdentifierExpr.ResolverType_Module) { - Error(e.tok, "name of module ({0}) is used as a function", ((Resolver_IdentifierExpr)lhs).Decl.Name); + reporter.Error(MessageSource.Resolver, e.tok, "name of module ({0}) is used as a function", ((Resolver_IdentifierExpr)lhs).Decl.Name); } else if (lhs != null && lhs.Type is Resolver_IdentifierExpr.ResolverType_Type) { // It may be a conversion expression var ri = (Resolver_IdentifierExpr)lhs; if (ri.TypeParamDecl != null) { - Error(e.tok, "name of type parameter ({0}) is used as a function", ri.TypeParamDecl.Name); + reporter.Error(MessageSource.Resolver, e.tok, "name of type parameter ({0}) is used as a function", ri.TypeParamDecl.Name); } else { var decl = ri.Decl; var ty = new UserDefinedType(e.tok, decl.Name, decl, ri.TypeArgs); if (ty.AsNewtype != null) { if (e.Args.Count != 1) { - Error(e.tok, "conversion operation to {0} got wrong number of arguments (expected 1, got {1})", decl.Name, e.Args.Count); + reporter.Error(MessageSource.Resolver, e.tok, "conversion operation to {0} got wrong number of arguments (expected 1, got {1})", decl.Name, e.Args.Count); } var conversionArg = 1 <= e.Args.Count ? e.Args[0] : ty.IsNumericBased(Type.NumericPersuation.Int) ? LiteralExpr.CreateIntLiteral(e.tok, 0) : @@ -9037,7 +8921,7 @@ namespace Microsoft.Dafny ResolveExpression(e.Args[i], opts); } } else { - Error(e.tok, "name of type ({0}) is used as a function", decl.Name); + reporter.Error(MessageSource.Resolver, e.tok, "name of type ({0}) is used as a function", decl.Name); } } } else { @@ -9047,10 +8931,10 @@ namespace Microsoft.Dafny var cRhs = new MethodCallInformation(e.tok, mse, e.Args); return cRhs; } else { - Error(e.tok, "method call is not allowed to be used in an expression context ({0})", mse.Member.Name); + reporter.Error(MessageSource.Resolver, e.tok, "method call is not allowed to be used in an expression context ({0})", mse.Member.Name); } } else if (lhs != null) { // if e.Lhs.Resolved is null, then e.Lhs was not successfully resolved and an error has already been reported - Error(e.tok, "non-function expression (of type {0}) is called with parameters", e.Lhs.Type); + reporter.Error(MessageSource.Resolver, e.tok, "non-function expression (of type {0}) is called with parameters", e.Lhs.Type); } } } else { @@ -9058,14 +8942,14 @@ namespace Microsoft.Dafny var callee = mse == null ? null : mse.Member as Function; if (fnType.Arity != e.Args.Count) { var what = callee != null ? string.Format("function '{0}'", callee.Name) : string.Format("function type '{0}'", fnType); - Error(e.tok, "wrong number of arguments to function application ({0} expects {1}, got {2})", what, fnType.Arity, e.Args.Count); + reporter.Error(MessageSource.Resolver, e.tok, "wrong number of arguments to function application ({0} expects {1}, got {2})", what, fnType.Arity, e.Args.Count); } else { for (var i = 0; i < fnType.Arity; i++) { if (!UnifyTypes(fnType.Args[i], e.Args[i].Type)) { - Error(e.Args[i].tok, "type mismatch for argument {0} (function expects {1}, got {2})", i, fnType.Args[i], e.Args[i].Type); + reporter.Error(MessageSource.Resolver, e.Args[i].tok, "type mismatch for argument {0} (function expects {1}, got {2})", i, fnType.Args[i], e.Args[i].Type); } } - if (errorCount != ErrorCount) { + if (errorCount != reporter.Count(ErrorLevel.Error)) { // do nothing else; error has been reported } else if (callee != null) { // produce a FunctionCallExpr instead of an ApplyExpr(MemberSelectExpr) @@ -9090,7 +8974,7 @@ namespace Microsoft.Dafny Contract.Assert(farg.Type != null); // follows from postcondition of ResolveExpression Type s = SubstType(callee.Formals[i].Type, rr.TypeArgumentSubstitutions); if (!UnifyTypes(farg.Type, s)) { - Error(rr, "incorrect type of function argument {0} (expected {1}, got {2})", i, s, farg.Type); + reporter.Error(MessageSource.Resolver, rr, "incorrect type of function argument {0} (expected {1}, got {2})", i, s, farg.Type); } } rr.Type = SubstType(callee.ResultType, rr.TypeArgumentSubstitutions); @@ -9132,12 +9016,12 @@ namespace Microsoft.Dafny DatatypeCtor ctor; if (!datatypeCtors[dt].TryGetValue(dtv.MemberName, out ctor)) { - Error(dtv.tok, "undeclared constructor {0} in datatype {1}", dtv.MemberName, dtv.DatatypeName); + reporter.Error(MessageSource.Resolver, dtv.tok, "undeclared constructor {0} in datatype {1}", dtv.MemberName, dtv.DatatypeName); } else { Contract.Assert(ctor != null); // follows from postcondition of TryGetValue dtv.Ctor = ctor; if (ctor.Formals.Count != dtv.Arguments.Count) { - Error(dtv.tok, "wrong number of arguments to datatype constructor {0} (found {1}, expected {2})", ctor.Name, dtv.Arguments.Count, ctor.Formals.Count); + reporter.Error(MessageSource.Resolver, dtv.tok, "wrong number of arguments to datatype constructor {0} (found {1}, expected {2})", ctor.Name, dtv.Arguments.Count, ctor.Formals.Count); } } int j = 0; @@ -9148,7 +9032,7 @@ namespace Microsoft.Dafny if (formal != null) { Type st = SubstType(formal.Type, subst); if (!UnifyTypes(arg.Type, st)) { - Error(arg.tok, "incorrect type of datatype constructor argument (found {0}, expected {1})", arg.Type, st); + reporter.Error(MessageSource.Resolver, arg.tok, "incorrect type of datatype constructor argument (found {0}, expected {1})", arg.Type, st); } } j++; @@ -9192,14 +9076,14 @@ namespace Microsoft.Dafny if (expr is IdentifierExpr) { var e = (IdentifierExpr)expr; if (e.Var != null && e.Var.IsGhost) { - Error(expr, "ghost variables are allowed only in specification contexts"); + reporter.Error(MessageSource.Resolver, expr, "ghost variables are allowed only in specification contexts"); return; } } else if (expr is MemberSelectExpr) { var e = (MemberSelectExpr)expr; if (e.Member != null && e.Member.IsGhost) { - Error(expr, "ghost fields are allowed only in specification contexts"); + reporter.Error(MessageSource.Resolver, expr, "ghost fields are allowed only in specification contexts"); return; } @@ -9207,7 +9091,7 @@ namespace Microsoft.Dafny var e = (FunctionCallExpr)expr; if (e.Function != null) { if (e.Function.IsGhost) { - Error(expr, "function calls are allowed only in specification contexts (consider declaring the function a 'function method')"); + reporter.Error(MessageSource.Resolver, expr, "function calls are allowed only in specification contexts (consider declaring the function a 'function method')"); return; } // function is okay, so check all NON-ghost arguments @@ -9232,13 +9116,13 @@ namespace Microsoft.Dafny return; } else if (expr is OldExpr) { - Error(expr, "old expressions are allowed only in specification and ghost contexts"); + reporter.Error(MessageSource.Resolver, expr, "old expressions are allowed only in specification and ghost contexts"); return; } else if (expr is UnaryOpExpr) { var e = (UnaryOpExpr)expr; if (e.Op == UnaryOpExpr.Opcode.Fresh) { - Error(expr, "fresh expressions are allowed only in specification and ghost contexts"); + reporter.Error(MessageSource.Resolver, expr, "fresh expressions are allowed only in specification and ghost contexts"); return; } @@ -9253,7 +9137,7 @@ namespace Microsoft.Dafny switch (e.ResolvedOp_PossiblyStillUndetermined) { case BinaryExpr.ResolvedOpcode.RankGt: case BinaryExpr.ResolvedOpcode.RankLt: - Error(expr, "rank comparisons are allowed only in specification and ghost contexts"); + reporter.Error(MessageSource.Resolver, expr, "rank comparisons are allowed only in specification and ghost contexts"); return; default: break; @@ -9264,7 +9148,7 @@ namespace Microsoft.Dafny switch (e.Op) { case TernaryExpr.Opcode.PrefixEqOp: case TernaryExpr.Opcode.PrefixNeqOp: - Error(expr, "prefix equalities are allowed only in specification and ghost contexts"); + reporter.Error(MessageSource.Resolver, expr, "prefix equalities are allowed only in specification and ghost contexts"); return; default: break; @@ -9294,7 +9178,7 @@ namespace Microsoft.Dafny var e = (QuantifierExpr)expr; if (e.MissingBounds != null) { foreach (var bv in e.MissingBounds) { - Error(expr, "quantifiers in non-ghost contexts must be compilable, but Dafny's heuristics can't figure out how to produce a bounded set of values for '{0}'", bv.Name); + reporter.Error(MessageSource.Resolver, expr, "quantifiers in non-ghost contexts must be compilable, but Dafny's heuristics can't figure out how to produce a bounded set of values for '{0}'", bv.Name); } return; } @@ -9302,7 +9186,7 @@ namespace Microsoft.Dafny var e = (MapComprehension)expr; if (e.MissingBounds != null && !e.Finite) { foreach (var bv in e.MissingBounds) { - Error(expr, "imaps in non-ghost contexts must be compilable, but Dafny's heuristics can't figure out how to produce a bounded set of values for '{0}'", bv.Name); + reporter.Error(MessageSource.Resolver, expr, "imaps in non-ghost contexts must be compilable, but Dafny's heuristics can't figure out how to produce a bounded set of values for '{0}'", bv.Name); } return; } @@ -9339,9 +9223,9 @@ namespace Microsoft.Dafny if (member == null) { // error has already been reported by ResolveMember } else if (member is Method) { - Error(e, "member {0} in type {1} refers to a method, but only functions can be used in this context", e.Name, cce.NonNull(ctype).Name); + reporter.Error(MessageSource.Resolver, e, "member {0} in type {1} refers to a method, but only functions can be used in this context", e.Name, cce.NonNull(ctype).Name); } else if (!(member is Function)) { - Error(e, "member {0} in type {1} does not refer to a function", e.Name, cce.NonNull(ctype).Name); + reporter.Error(MessageSource.Resolver, e, "member {0} in type {1} does not refer to a function", e.Name, cce.NonNull(ctype).Name); } else { Function function = (Function)member; e.Function = function; @@ -9349,10 +9233,10 @@ namespace Microsoft.Dafny ((FixpointPredicate)function).Uses.Add(e); } if (e.Receiver is StaticReceiverExpr && !function.IsStatic) { - Error(e, "an instance function must be selected via an object, not just a class name"); + reporter.Error(MessageSource.Resolver, e, "an instance function must be selected via an object, not just a class name"); } if (function.Formals.Count != e.Args.Count) { - Error(e, "wrong number of function arguments (got {0}, expected {1})", e.Args.Count, function.Formals.Count); + reporter.Error(MessageSource.Resolver, e, "wrong number of function arguments (got {0}, expected {1})", e.Args.Count, function.Formals.Count); } else { Contract.Assert(ctype != null); // follows from postcondition of ResolveMember if (!function.IsStatic) { @@ -9364,9 +9248,9 @@ namespace Microsoft.Dafny // in the event that a static function calls another static function (and note that we need the // type of the receiver in order to find the method, so we could not have made this check // earlier). - Error(e.Receiver, "'this' is not allowed in a 'static' context"); + reporter.Error(MessageSource.Resolver, e.Receiver, "'this' is not allowed in a 'static' context"); } else if (e.Receiver is StaticReceiverExpr) { - Error(e.Receiver, "call to instance function requires an instance"); + reporter.Error(MessageSource.Resolver, e.Receiver, "call to instance function requires an instance"); } } // build the type substitution map @@ -9384,7 +9268,7 @@ namespace Microsoft.Dafny Contract.Assert(farg.Type != null); // follows from postcondition of ResolveExpression Type s = SubstType(function.Formals[i].Type, e.TypeArgumentSubstitutions); if (!UnifyTypes(farg.Type, s)) { - Error(e, "incorrect type of function argument {0} (expected {1}, got {2})", i, s, farg.Type); + reporter.Error(MessageSource.Resolver, e, "incorrect type of function argument {0} (expected {1}, got {2})", i, s, farg.Type); } } e.Type = SubstType(function.ResultType, e.TypeArgumentSubstitutions); @@ -9435,8 +9319,8 @@ namespace Microsoft.Dafny /// /// For a description, see DiscoverBoundsAux. /// - public static List DiscoverBounds(IToken tok, List bvars, Expression expr, bool polarity, bool returnAllBounds, List missingBounds) where VT : IVariable { - var pairs = DiscoverBoundsAux(tok, bvars, expr, polarity, returnAllBounds, false, missingBounds); + public static List DiscoverBounds(IToken tok, List bvars, Expression expr, bool polarity, bool returnAllBounds, List missingBounds, ErrorReporter reporter) where VT : IVariable { + var pairs = DiscoverBoundsAux(tok, bvars, expr, polarity, returnAllBounds, false, missingBounds, reporter); if (pairs == null) { return null; } @@ -9464,7 +9348,7 @@ namespace Microsoft.Dafny /// If "allowAnyIntegers", then integer variables will always be given a bound, but this bound may be WiggleWaggle if /// there is no better bound. /// - public static List>> DiscoverBoundsAux(IToken tok, List bvars, Expression expr, bool polarity, bool returnAllBounds, bool allowAnyIntegers, List missingBounds) where VT : IVariable { + public static List>> DiscoverBoundsAux(IToken tok, List bvars, Expression expr, bool polarity, bool returnAllBounds, bool allowAnyIntegers, List missingBounds, ErrorReporter reporter) where VT : IVariable { Contract.Requires(tok != null); Contract.Requires(bvars != null); Contract.Requires(missingBounds != null); @@ -9483,7 +9367,7 @@ namespace Microsoft.Dafny var allBounds = new List>>(); bool foundError = false; foreach (var bv in bvars) { - var c = TypeConstraint(bv, bv.Type); + var c = TypeConstraint(bv, bv.Type, reporter); expr = polarity ? Expression.CreateAnd(c, expr) : Expression.CreateImplies(c, expr); } for (int j = 0; j < bvars.Count; j++) { @@ -9619,15 +9503,15 @@ namespace Microsoft.Dafny return foundError ? null : allBounds; } - static Expression TypeConstraint(IVariable bv, Type ty) { + static Expression TypeConstraint(IVariable bv, Type ty, ErrorReporter reporter) { Contract.Requires(bv != null); Contract.Requires(ty != null); ty = ty.NormalizeExpand(); var dd = ty.AsNewtype; if (dd != null) { - var c = TypeConstraint(bv, dd.BaseType); + var c = TypeConstraint(bv, dd.BaseType, reporter); if (dd.Var != null) { - c = Expression.CreateAnd(c, new Translator().Substitute(dd.Constraint, dd.Var, Expression.CreateIdentExpr(bv))); + c = Expression.CreateAnd(c, new Translator(reporter).Substitute(dd.Constraint, dd.Var, Expression.CreateIdentExpr(bv))); } return c; } @@ -9971,7 +9855,7 @@ namespace Microsoft.Dafny IndexableTypeProxy expectedType = new IndexableTypeProxy(domainType, elementType, argType, true, true, true); if (!UnifyTypes(e.Seq.Type, expectedType)) { - Error(e, "sequence/array/multiset/map selection requires a sequence, array, multiset, or map (got {0})", e.Seq.Type); + reporter.Error(MessageSource.Resolver, e, "sequence/array/multiset/map selection requires a sequence, array, multiset, or map (got {0})", e.Seq.Type); seqErr = true; } if (!e.SelectOne) // require sequence or array @@ -9979,13 +9863,13 @@ namespace Microsoft.Dafny if (!allowNonUnitArraySelection) { // require seq if (!UnifyTypes(expectedType, new SeqType(new InferredTypeProxy()))) { - Error(e, "selection requires a sequence (got {0})", e.Seq.Type); + reporter.Error(MessageSource.Resolver, e, "selection requires a sequence (got {0})", e.Seq.Type); } } else { if (UnifyTypes(expectedType, new MapType(true, new InferredTypeProxy(), new InferredTypeProxy()))) { - Error(e, "cannot multiselect a map (got {0} as map type)", e.Seq.Type); + reporter.Error(MessageSource.Resolver, e, "cannot multiselect a map (got {0} as map type)", e.Seq.Type); } else if (UnifyTypes(expectedType, new MapType(false, new InferredTypeProxy(), new InferredTypeProxy()))) { - Error(e, "cannot multiselect an imap (got {0} as imap type)", e.Seq.Type); + reporter.Error(MessageSource.Resolver, e, "cannot multiselect an imap (got {0} as imap type)", e.Seq.Type); } } } @@ -9993,7 +9877,7 @@ namespace Microsoft.Dafny ResolveExpression(e.E0, opts); Contract.Assert(e.E0.Type != null); // follows from postcondition of ResolveExpression if (!UnifyTypes(e.E0.Type, domainType)) { - Error(e.E0, "sequence/array/multiset/map selection requires {1} indices (got {0})", e.E0.Type, domainType); + reporter.Error(MessageSource.Resolver, e.E0, "sequence/array/multiset/map selection requires {1} indices (got {0})", e.E0.Type, domainType); } } if (e.E1 != null) { @@ -10001,7 +9885,7 @@ namespace Microsoft.Dafny Contract.Assert(e.E1.Type != null); // follows from postcondition of ResolveExpression var domType = e.E0 == null ? domainType : new OperationTypeProxy(true, false, false, false, false, false); // reuse 'domainType' if .E0 did not use it; otherwise, create a new proxy to allow .E1 to be any integer-based numeric type, independent of the integer-based numeric type used by .E0 if (!UnifyTypes(e.E1.Type, domType)) { - Error(e.E1, "sequence/array/multiset/map selection requires {1} indices (got {0})", e.E1.Type, domType); + reporter.Error(MessageSource.Resolver, e.E1, "sequence/array/multiset/map selection requires {1} indices (got {0})", e.E1.Type, domType); } } if (!seqErr) { @@ -10193,7 +10077,7 @@ namespace Microsoft.Dafny } else { return false; } - } else if (expr is SeqSelectExpr) { + } else if (expr is SeqSelectExpr) { SeqSelectExpr e = (SeqSelectExpr)expr; return UsesSpecFeatures(e.Seq) || (e.E0 != null && UsesSpecFeatures(e.E0)) || diff --git a/Source/Dafny/Rewriter.cs b/Source/Dafny/Rewriter.cs index 4223fb7f..cb71b80d 100644 --- a/Source/Dafny/Rewriter.cs +++ b/Source/Dafny/Rewriter.cs @@ -6,24 +6,25 @@ using IToken = Microsoft.Boogie.IToken; namespace Microsoft.Dafny { - [ContractClass(typeof(IRewriterContracts))] - public interface IRewriter + public abstract class IRewriter { - void PreResolve(ModuleDefinition m); - void PostResolve(ModuleDefinition m); - // After SCC/Cyclicity/Recursivity analysis: - void PostCyclicityResolve(ModuleDefinition m); - } - [ContractClassFor(typeof(IRewriter))] - abstract class IRewriterContracts : IRewriter - { - public void PreResolve(ModuleDefinition m) { + protected readonly ErrorReporter reporter; + + public IRewriter(ErrorReporter reporter) { + Contract.Requires(reporter != null); + this.reporter = reporter; + } + + internal virtual void PreResolve(ModuleDefinition m) { Contract.Requires(m != null); } - public void PostResolve(ModuleDefinition m) { + + internal virtual void PostResolve(ModuleDefinition m) { Contract.Requires(m != null); } - public void PostCyclicityResolve(ModuleDefinition m) { + + // After SCC/Cyclicity/Recursivity analysis: + internal virtual void PostCyclicityResolve(ModuleDefinition m) { Contract.Requires(m != null); } } @@ -37,33 +38,26 @@ namespace Microsoft.Dafny } } - public class TriggersRewriter : IRewriter { - Resolver Resolver; - - internal TriggersRewriter(Resolver resolver) { - Contract.Requires(resolver != null); - this.Resolver = resolver; + public class TriggerGeneratingRewriter : IRewriter { + internal TriggerGeneratingRewriter(ErrorReporter reporter) : base(reporter) { + Contract.Requires(reporter != null); } - public void PreResolve(ModuleDefinition m) { } - - public void PostResolve(ModuleDefinition m) { + internal override void PostResolve(ModuleDefinition m) { foreach (var decl in ModuleDefinition.AllCallables(m.TopLevelDecls)) { if (decl is Function) { var function = (Function)decl; - TriggerGenerator.AddTriggers(function.Ens, Resolver); - TriggerGenerator.AddTriggers(function.Req, Resolver); - TriggerGenerator.AddTriggers(function.Body, Resolver); + //TriggerGenerator.AddTriggers(function.Ens, Resolver); + //TriggerGenerator.AddTriggers(function.Req, Resolver); + //TriggerGenerator.AddTriggers(function.Body, Resolver); } else if (decl is Method) { var method = (Method)decl; - TriggerGenerator.AddTriggers(method.Ens, Resolver); - TriggerGenerator.AddTriggers(method.Req, Resolver); - TriggerGenerator.AddTriggers(method.Body, Resolver); + //TriggerGenerator.AddTriggers(method.Ens, Resolver); + //TriggerGenerator.AddTriggers(method.Req, Resolver); + //TriggerGenerator.AddTriggers(method.Body, Resolver); } } } - - public void PostCyclicityResolve(ModuleDefinition m) { } } /// @@ -106,7 +100,12 @@ namespace Microsoft.Dafny /// public class AutoContractsRewriter : IRewriter { - public void PreResolve(ModuleDefinition m) { + public AutoContractsRewriter(ErrorReporter reporter) + : base(reporter) { + Contract.Requires(reporter != null); + } + + internal override void PreResolve(ModuleDefinition m) { foreach (var d in m.TopLevelDecls) { bool sayYes = true; if (d is ClassDecl && Attributes.ContainsBool(d.Attributes, "autocontracts", ref sayYes) && sayYes) { @@ -162,7 +161,7 @@ namespace Microsoft.Dafny } } - public void PostResolve(ModuleDefinition m) { + internal override void PostResolve(ModuleDefinition m) { foreach (var d in m.TopLevelDecls) { bool sayYes = true; if (d is ClassDecl && Attributes.ContainsBool(d.Attributes, "autocontracts", ref sayYes) && sayYes) { @@ -171,9 +170,6 @@ namespace Microsoft.Dafny } } - public void PostCyclicityResolve(ModuleDefinition m) { - } - void ProcessClassPostResolve(ClassDecl cl) { // Find all fields of a reference type, and make a note of whether or not the reference type has a Repr field. // Also, find the Repr field and the function Valid in class "cl" @@ -416,20 +412,20 @@ namespace Microsoft.Dafny /// specifically asks to see it via the reveal_foo() lemma /// public class OpaqueFunctionRewriter : IRewriter { - readonly ResolutionErrorReporter reporter; protected Dictionary fullVersion; // Given an opaque function, retrieve the full protected Dictionary original; // Given a full version of an opaque function, find the original opaque version protected Dictionary revealOriginal; // Map reveal_* lemmas back to their original functions - public OpaqueFunctionRewriter(ResolutionErrorReporter reporter) - : base() { - this.reporter = reporter; + public OpaqueFunctionRewriter(ErrorReporter reporter) + : base(reporter) { + Contract.Requires(reporter != null); + fullVersion = new Dictionary(); original = new Dictionary(); revealOriginal = new Dictionary(); } - public void PreResolve(ModuleDefinition m) { + internal override void PreResolve(ModuleDefinition m) { foreach (var d in m.TopLevelDecls) { if (d is ClassDecl) { DuplicateOpaqueClassFunctions((ClassDecl)d); @@ -437,7 +433,7 @@ namespace Microsoft.Dafny } } - public void PostResolve(ModuleDefinition m) { + internal override void PostResolve(ModuleDefinition m) { // Fix up the ensures clause of the full version of the function, // since it may refer to the original opaque function foreach (var fn in ModuleDefinition.AllFunctions(m.TopLevelDecls)) { @@ -462,7 +458,7 @@ namespace Microsoft.Dafny } } - public void PostCyclicityResolve(ModuleDefinition m) { + internal override void PostCyclicityResolve(ModuleDefinition m) { // Add layer quantifier if the function is recursive foreach (var decl in ModuleDefinition.AllCallables(m.TopLevelDecls)) { if (decl is Lemma) { @@ -507,7 +503,7 @@ namespace Microsoft.Dafny if (!Attributes.Contains(f.Attributes, "opaque")) { // Nothing to do } else if (f.IsProtected) { - reporter.Error(f.tok, ":opaque is not allowed to be applied to protected functions (this will be allowed when the language introduces 'opaque'/'reveal' as keywords)"); + reporter.Error(MessageSource.Rewriter, f.tok, ":opaque is not allowed to be applied to protected functions (this will be allowed when the language introduces 'opaque'/'reveal' as keywords)"); } else if (!RefinementToken.IsInherited(f.tok, c.Module)) { // Create a copy, which will be the internal version with a full body // which will allow us to verify that the ensures are true @@ -721,19 +717,16 @@ namespace Microsoft.Dafny /// public class AutoReqFunctionRewriter : IRewriter { Function parentFunction; - Resolver resolver; OpaqueFunctionRewriter opaqueInfo; bool containsMatch; // TODO: Track this per-requirement, rather than per-function - public AutoReqFunctionRewriter(Resolver r, OpaqueFunctionRewriter o) { - this.resolver = r; + public AutoReqFunctionRewriter(ErrorReporter reporter, OpaqueFunctionRewriter o) + : base(reporter) { + Contract.Requires(reporter != null); this.opaqueInfo = o; } - public void PreResolve(ModuleDefinition m) { - } - - public void PostResolve(ModuleDefinition m) { + internal override void PostResolve(ModuleDefinition m) { var components = m.CallGraph.TopologicallySortedComponents(); foreach (var scComponent in components) { // Visit the call graph bottom up, so anything we call already has its prequisites calculated @@ -806,9 +799,6 @@ namespace Microsoft.Dafny } } - public void PostCyclicityResolve(ModuleDefinition m) { - } - Expression subVars(List formals, List values, Expression e, Expression f_this) { Contract.Assert(formals != null); Contract.Assert(values != null); @@ -839,7 +829,7 @@ namespace Microsoft.Dafny } if (!tip.Equals("")) { - resolver.ReportAdditionalInformation(f.tok, tip, f.tok.val.Length); + reporter.Info(MessageSource.Rewriter, f.tok, tip); if (DafnyOptions.O.AutoReqPrintFile != null) { using (System.IO.TextWriter writer = new System.IO.StreamWriter(DafnyOptions.O.AutoReqPrintFile, true)) { writer.WriteLine(f.Name); @@ -866,7 +856,7 @@ namespace Microsoft.Dafny } if (!tip.Equals("")) { - resolver.ReportAdditionalInformation(method.tok, tip, method.tok.val.Length); + reporter.Info(MessageSource.Rewriter, method.tok, tip); if (DafnyOptions.O.AutoReqPrintFile != null) { using (System.IO.TextWriter writer = new System.IO.StreamWriter(DafnyOptions.O.AutoReqPrintFile, true)) { writer.WriteLine(method.Name); @@ -1061,7 +1051,7 @@ namespace Microsoft.Dafny Expression allReqsSatisfied = andify(e.Term.tok, auto_reqs); Expression allReqsSatisfiedAndTerm = Expression.CreateAnd(allReqsSatisfied, e.Term); e.UpdateTerm(allReqsSatisfiedAndTerm); - resolver.ReportAdditionalInformation(e.tok, "autoreq added (" + Printer.ExtendedExprToString(allReqsSatisfied) + ") &&", e.tok.val.Length); + reporter.Info(MessageSource.Rewriter, e.tok, "autoreq added (" + Printer.ExtendedExprToString(allReqsSatisfied) + ") &&"); } } else if (expr is SetComprehension) { var e = (SetComprehension)expr; @@ -1108,7 +1098,12 @@ namespace Microsoft.Dafny /// public class TimeLimitRewriter : IRewriter { - public void PreResolve(ModuleDefinition m) { + public TimeLimitRewriter(ErrorReporter reporter) + : base(reporter) { + Contract.Requires(reporter != null); + } + + internal override void PreResolve(ModuleDefinition m) { foreach (var d in m.TopLevelDecls) { if (d is ClassDecl) { var c = (ClassDecl)d; @@ -1136,16 +1131,6 @@ namespace Microsoft.Dafny } } } - - public void PostResolve(ModuleDefinition m) - { - // Nothing to do here - } - - public void PostCyclicityResolve(ModuleDefinition m) { - // Nothing to do here - } - } diff --git a/Source/Dafny/Scanner.cs b/Source/Dafny/Scanner.cs index a73f510d..e6c97f22 100644 --- a/Source/Dafny/Scanner.cs +++ b/Source/Dafny/Scanner.cs @@ -314,8 +314,8 @@ public class Scanner { // [NotDelayed] public Scanner (string/*!*/ fullFilename, string/*!*/ fileName, Errors/*!*/ errorHandler, bool useBaseName = false) : base() { - Contract.Requires(fileName != null); - Contract.Requires(errorHandler != null); + Contract.Requires(fileName != null); + Contract.Requires(errorHandler != null); this.errorHandler = errorHandler; pt = tokens = new Token(); // first token is a dummy t = new Token(); // dummy because t is a non-null field @@ -332,9 +332,9 @@ public class Scanner { // [NotDelayed] public Scanner (Stream/*!*/ s, Errors/*!*/ errorHandler, string/*!*/ fullFilename, string/*!*/ fileName, bool useBaseName = false) : base() { - Contract.Requires(s != null); - Contract.Requires(errorHandler != null); - Contract.Requires(fileName != null); + Contract.Requires(s != null); + Contract.Requires(errorHandler != null); + Contract.Requires(fileName != null); pt = tokens = new Token(); // first token is a dummy t = new Token(); // dummy because t is a non-null field this._buffer = new Buffer(s, true); @@ -344,9 +344,9 @@ public class Scanner { Init(); } - string GetBaseName(string fileName) { - return System.IO.Path.GetFileName(fileName); // Return basename - } + string GetBaseName(string fileName) { + return System.IO.Path.GetFileName(fileName); // Return basename + } void Init() { pos = -1; line = 1; col = 0; @@ -991,6 +991,4 @@ public class Scanner { } // end Scanner public delegate void ErrorProc(int n, string filename, int line, int col); - - } \ No newline at end of file diff --git a/Source/Dafny/Translator.cs b/Source/Dafny/Translator.cs index b8c4b8ec..039aa56f 100644 --- a/Source/Dafny/Translator.cs +++ b/Source/Dafny/Translator.cs @@ -93,9 +93,13 @@ namespace Microsoft.Dafny { } public class Translator { + readonly ErrorReporter reporter; [NotDelayed] - public Translator() { + public Translator(ErrorReporter reporter) { + Contract.Requires(reporter != null); + + this.reporter = reporter; InsertChecksums = 0 < CommandLineOptions.Clo.VerifySnapshots; Bpl.Program boogieProgram = ReadPrelude(); if (boogieProgram != null) { @@ -3609,7 +3613,7 @@ namespace Microsoft.Dafny { Contract.Requires(tok != null); Contract.Ensures(Contract.Result() != null); var col = tok.col + (isEndToken ? tok.val.Length : 0); - string description = Util.ReportIssueToString_Bare(additionalInfo == null ? "" : ": ", tok.filename, tok.line, tok.col, additionalInfo ?? ""); + string description = reporter.ErrorToString_Internal(additionalInfo == null ? "" : ": ", tok.filename, tok.line, tok.col, additionalInfo ?? ""); QKeyValue kv = new QKeyValue(tok, "captureState", new List() { description }, null); return new Bpl.AssumeCmd(tok, Bpl.Expr.True, kv); } @@ -7679,7 +7683,7 @@ namespace Microsoft.Dafny { } var missingBounds = new List(); - var bounds = Resolver.DiscoverBounds(x.tok, new List() { x }, expr, true, true, missingBounds); + var bounds = Resolver.DiscoverBounds(x.tok, new List() { x }, expr, true, true, missingBounds, reporter); if (missingBounds.Count == 0) { foreach (var bound in bounds) { if (bound is ComprehensionExpr.IntBoundedPool) { @@ -12955,9 +12959,8 @@ namespace Microsoft.Dafny { return true; } else { // Skip inlining, as it would cause arbitrary expressions to pop up in the trigger - // CLEMENT: Report inlining issue in a VS plugin friendly way - //CLEMENT this should appear at the outmost call site, not at the innermost. See SnapshotableTrees.dfy - Dafny.Util.ReportIssue("Info", fexp.tok, "Some instances of this call cannot safely be inlined."); + // CLEMENT this should appear at the outmost call site, not at the innermost. See SnapshotableTrees.dfy + reporter.Info(MessageSource.Translator, fexp.tok, "Some instances of this call cannot safely be inlined."); } } diff --git a/Source/Dafny/TriggerGenerator.cs b/Source/Dafny/TriggerGenerator.cs index cf677e0e..04d96b01 100644 --- a/Source/Dafny/TriggerGenerator.cs +++ b/Source/Dafny/TriggerGenerator.cs @@ -513,7 +513,7 @@ namespace Microsoft.Dafny { return; DebugTriggers("== From {0} visiting expr: {1}", new StackFrame(1).GetMethod().Name, Printer.ExprToString(root)); - TriggerGenerator generator = new TriggerGenerator(resolver.ReportAdditionalInformation); + TriggerGenerator generator = new TriggerGenerator(null); generator.AddTriggers_Internal(root); } @@ -522,7 +522,7 @@ namespace Microsoft.Dafny { return; DebugTriggers("== From {0} visiting statement: {1}", new StackFrame(1).GetMethod().Name, Printer.StatementToString(root)); - TriggerGenerator generator = new TriggerGenerator(resolver.ReportAdditionalInformation); + TriggerGenerator generator = new TriggerGenerator(null); generator.AddTriggers_Internal(root); } diff --git a/Source/Dafny/Util.cs b/Source/Dafny/Util.cs index 508d23c6..eaf599e3 100644 --- a/Source/Dafny/Util.cs +++ b/Source/Dafny/Util.cs @@ -67,29 +67,6 @@ namespace Microsoft.Dafny { return res; } - public static void ReportIssue(string header, IToken tok, string msg, params object[] args) { - ReportIssue(header, tok, String.Format(msg, args)); - } - - public static void ReportIssue(string header, IToken tok, string msg) { - ReportIssue(header, tok.filename, tok.line, tok.col, msg); - } - - public static void ReportIssue(string header, string filename, int line, int column, string msg) { - Console.WriteLine(ReportIssueToString(header, filename, line, column, msg)); - } - - public static string ReportIssueToString(string header, string filename, int line, int column, string msg) { - Contract.Requires(header != null); - Contract.Requires(filename != null); - Contract.Requires(msg != null); - return ReportIssueToString_Bare(": " + header, filename, line, column, ": " + msg); - } - - public static string ReportIssueToString_Bare(string header, string filename, int line, int column, string msg) { - return String.Format("{0}({1},{2}){3}{4}", filename, line, column - 1, header, msg ?? ""); - } - /// /// Returns s but with all occurrences of '_' removed. /// diff --git a/Source/DafnyDriver/DafnyDriver.cs b/Source/DafnyDriver/DafnyDriver.cs index d22899ab..4b5ae8d8 100644 --- a/Source/DafnyDriver/DafnyDriver.cs +++ b/Source/DafnyDriver/DafnyDriver.cs @@ -22,7 +22,6 @@ namespace Microsoft.Dafny public class DafnyDriver { - enum ExitValue { VERIFIED = 0, PREPROCESSING_ERROR, DAFNY_ERROR, NOT_VERIFIED } @@ -42,8 +41,7 @@ namespace Microsoft.Dafny { Contract.Requires(cce.NonNullElements(args)); - printer = new DafnyConsolePrinter(); - ExecutionEngine.printer = printer; + ExecutionEngine.printer = new DafnyConsolePrinter(); // For boogie errors DafnyOptions.Install(new DafnyOptions()); @@ -57,14 +55,14 @@ namespace Microsoft.Dafny if (CommandLineOptions.Clo.Files.Count == 0) { - printer.ErrorWriteLine(Console.Out, "*** Error: No input files were specified."); + ExecutionEngine.printer.ErrorWriteLine(Console.Out, "*** Error: No input files were specified."); exitValue = ExitValue.PREPROCESSING_ERROR; goto END; } if (CommandLineOptions.Clo.XmlSink != null) { string errMsg = CommandLineOptions.Clo.XmlSink.Open(); if (errMsg != null) { - printer.ErrorWriteLine(Console.Out, "*** Error: " + errMsg); + ExecutionEngine.printer.ErrorWriteLine(Console.Out, "*** Error: " + errMsg); exitValue = ExitValue.PREPROCESSING_ERROR; goto END; } @@ -87,12 +85,11 @@ namespace Microsoft.Dafny {Contract.Assert(file != null); string extension = Path.GetExtension(file); if (extension != null) { extension = extension.ToLower(); } - if (extension != ".dfy") - { - printer.ErrorWriteLine(Console.Out, "*** Error: '{0}': Filename extension '{1}' is not supported. Input files must be Dafny programs (.dfy).", file, - extension == null ? "" : extension); - exitValue = ExitValue.PREPROCESSING_ERROR; - goto END; + if (extension != ".dfy") { + ExecutionEngine.printer.ErrorWriteLine(Console.Out, "*** Error: '{0}': Filename extension '{1}' is not supported. Input files must be Dafny programs (.dfy).", file, + extension == null ? "" : extension); + exitValue = ExitValue.PREPROCESSING_ERROR; + goto END; } } exitValue = ProcessFiles(CommandLineOptions.Clo.Files); @@ -156,14 +153,15 @@ namespace Microsoft.Dafny using (XmlFileScope xf = new XmlFileScope(CommandLineOptions.Clo.XmlSink, fileNames[fileNames.Count-1])) { Dafny.Program dafnyProgram; + ErrorReporter reporter = new ConsoleErrorReporter(); string programName = fileNames.Count == 1 ? fileNames[0] : "the program"; - string err = Dafny.Main.ParseCheck(fileNames, programName, out dafnyProgram); + string err = Dafny.Main.ParseCheck(fileNames, programName, reporter, out dafnyProgram); if (err != null) { exitValue = ExitValue.DAFNY_ERROR; - printer.ErrorWriteLine(Console.Out, err); + ExecutionEngine.printer.ErrorWriteLine(Console.Out, err); } else if (dafnyProgram != null && !CommandLineOptions.Clo.NoResolve && !CommandLineOptions.Clo.NoTypecheck && DafnyOptions.O.DafnyVerify) { - Dafny.Translator translator = new Dafny.Translator(); + Dafny.Translator translator = new Dafny.Translator(dafnyProgram.reporter); Bpl.Program boogieProgram = translator.Translate(dafnyProgram); if (CommandLineOptions.Clo.PrintFile != null) { @@ -184,12 +182,12 @@ namespace Microsoft.Dafny var allOk = stats.ErrorCount == 0 && stats.InconclusiveCount == 0 && stats.TimeoutCount == 0 && stats.OutOfMemoryCount == 0; switch (oc) { case PipelineOutcome.VerificationCompleted: - printer.WriteTrailer(stats); + ExecutionEngine.printer.WriteTrailer(stats); if ((DafnyOptions.O.Compile && allOk && CommandLineOptions.Clo.ProcsToCheck == null) || DafnyOptions.O.ForceCompile) CompileDafnyProgram(dafnyProgram, fileNames[0]); break; case PipelineOutcome.Done: - printer.WriteTrailer(stats); + ExecutionEngine.printer.WriteTrailer(stats); if (DafnyOptions.O.ForceCompile) CompileDafnyProgram(dafnyProgram, fileNames[0]); break; @@ -265,10 +263,7 @@ namespace Microsoft.Dafny #region Output - - static OutputPrinter printer; - - + class DafnyConsolePrinter : ConsolePrinter { public override void ReportBplError(IToken tok, string message, bool error, TextWriter tw, string category = null) diff --git a/Source/DafnyExtension/DafnyDriver.cs b/Source/DafnyExtension/DafnyDriver.cs index 50d8c2e3..36664a9b 100644 --- a/Source/DafnyExtension/DafnyDriver.cs +++ b/Source/DafnyExtension/DafnyDriver.cs @@ -115,19 +115,21 @@ namespace DafnyLanguage bool ParseAndTypeCheck() { Dafny.ModuleDecl module = new Dafny.LiteralModuleDecl(new Dafny.DefaultModuleDecl(), null); Dafny.BuiltIns builtIns = new Dafny.BuiltIns(); - Dafny.Errors parseErrors = new VSErrors(this); + + var errorReporter = new VSErrorReporter(this); + var parseErrors = new Dafny.Errors(errorReporter); + int errorCount = Dafny.Parser.Parse(_snapshot.GetText(), _filename, _filename, module, builtIns, parseErrors); string errString = Dafny.Main.ParseIncludes(module, builtIns, new List(), parseErrors); if (errorCount != 0 || errString != null) return false; - Dafny.Program program = new Dafny.Program(_filename, module, builtIns); + Dafny.Program program = new Dafny.Program(_filename, module, builtIns, errorReporter); - var r = new VSResolver(program, this); + var r = new Resolver(program); r.ResolveProgram(program); - if (r.ErrorCount != 0) + if (errorReporter.Count(ErrorLevel.Error) != 0) return false; - program.AdditionalInformation.AddRange(r.AdditionalInformation); _program = program; return true; // success } @@ -137,56 +139,31 @@ namespace DafnyLanguage _errors.Add(new DafnyError(filename, line - 1, col - 1, cat, msg, _snapshot, isRecycled, null, System.IO.Path.GetFullPath(this._filename) == filename)); } - class VSErrors : Dafny.Errors - { - DafnyDriver dd; - public VSErrors(DafnyDriver dd) { - this.dd = dd; - } - public override void SynErr(string filename, int line, int col, string msg) { - dd.RecordError(filename, line, col, ErrorCategory.ParseError, msg); - count++; - } - public override void SemErr(string filename, int line, int col, string msg) { - dd.RecordError(filename, line, col, ErrorCategory.ResolveError, msg); - count++; - } - public override void Warning(IToken tok, string msg) { - dd.RecordError(tok.filename, tok.line, tok.col, ErrorCategory.ParseWarning, msg); - } - } - - class VSResolver : Dafny.Resolver + class VSErrorReporter : Dafny.ErrorReporter { DafnyDriver dd; - Dictionary> _additionalInformation = new Dictionary>(); - public List AdditionalInformation { get { return _additionalInformation.Values.SelectMany(i => i).ToList(); } } - public VSResolver(Dafny.Program program, DafnyDriver dd) - : base(program) { + public VSErrorReporter(DafnyDriver dd) { this.dd = dd; - - AdditionalInformationReporter = - (addinfo) - => - { - if (!_additionalInformation.ContainsKey(addinfo.Token)) { - _additionalInformation.Add(addinfo.Token, new HashSet()); - } - _additionalInformation[addinfo.Token].Add(addinfo); - }; - } - - public override void Error(Bpl.IToken tok, string msg, params object[] args) { - string s = string.Format(msg, args); - dd.RecordError(tok.filename, tok.line, tok.col, ErrorCategory.ResolveError, s); - ErrorCount++; } - public override void Warning(IToken tok, string msg, params object[] args) { - if (reportWarnings) { - string s = string.Format(msg, args); - dd.RecordError(tok.filename, tok.line, tok.col, ErrorCategory.ResolveWarning, s); + // TODO: The error tracking could be made better to track the full information returned by Dafny + public override bool Message(MessageSource source, ErrorLevel level, IToken tok, string msg) { + if (base.Message(source, level, tok, msg)) { + switch (level) { + case ErrorLevel.Error: + dd.RecordError(tok.filename, tok.line, tok.col, source == MessageSource.Parser ? ErrorCategory.ParseError : ErrorCategory.ResolveError, msg); + break; + case ErrorLevel.Warning: + dd.RecordError(tok.filename, tok.line, tok.col, source == MessageSource.Parser ? ErrorCategory.ParseWarning : ErrorCategory.ResolveWarning, msg); + break; + case ErrorLevel.Info: + // The AllMessages variable already keeps track of this + break; + } + return true; + } else { + return false; } } } @@ -273,7 +250,7 @@ namespace DafnyLanguage } public static bool Verify(Dafny.Program dafnyProgram, ResolverTagger resolver, string uniqueIdPrefix, string requestId, ErrorReporterDelegate er) { - Dafny.Translator translator = new Dafny.Translator(); + Dafny.Translator translator = new Dafny.Translator(dafnyProgram.reporter); translator.InsertChecksums = true; translator.UniqueIdPrefix = uniqueIdPrefix; Bpl.Program boogieProgram = translator.Translate(dafnyProgram); diff --git a/Source/DafnyExtension/IdentifierTagger.cs b/Source/DafnyExtension/IdentifierTagger.cs index 262dddcd..13991496 100644 --- a/Source/DafnyExtension/IdentifierTagger.cs +++ b/Source/DafnyExtension/IdentifierTagger.cs @@ -136,9 +136,9 @@ namespace DafnyLanguage List newRegions = new List(); - foreach (var addInfo in program.AdditionalInformation) + foreach (var info in program.reporter.AllMessages[ErrorLevel.Info]) { - IdRegion.Add(newRegions, addInfo.Token, addInfo.Text, addInfo.Length); + IdRegion.Add(newRegions, info.token, info.message, info.token.val.Length); } foreach (var module in program.Modules) { diff --git a/Source/DafnyExtension/ResolverTagger.cs b/Source/DafnyExtension/ResolverTagger.cs index 6eaec5a6..0ce68809 100644 --- a/Source/DafnyExtension/ResolverTagger.cs +++ b/Source/DafnyExtension/ResolverTagger.cs @@ -74,10 +74,10 @@ namespace DafnyLanguage switch (err.Category) { case ErrorCategory.ProcessError: case ErrorCategory.ParseError: - case ErrorCategory.ParseWarning: return "syntax error"; // COLOR: red case ErrorCategory.ResolveError: return "compiler error"; // COLOR: blue + case ErrorCategory.ParseWarning: case ErrorCategory.ResolveWarning: return "compiler warning"; // COLOR: blue case ErrorCategory.InternalError: @@ -403,7 +403,7 @@ namespace DafnyLanguage chng(this, new SnapshotSpanEventArgs(new SnapshotSpan(snapshot, 0, snapshot.Length))); } - static TaskErrorCategory CategoryConversion(ErrorCategory cat) + static TaskErrorCategory CategoryConversion(ErrorCategory cat) //CLEMENT: We've lost that info { switch (cat) { diff --git a/Source/DafnyServer/DafnyHelper.cs b/Source/DafnyServer/DafnyHelper.cs index 10d98677..d6c3f5c7 100644 --- a/Source/DafnyServer/DafnyHelper.cs +++ b/Source/DafnyServer/DafnyHelper.cs @@ -30,14 +30,14 @@ namespace Microsoft.Dafny { private string fname; private string source; - private Dafny.Errors errors; + private readonly Dafny.ErrorReporter reporter; private Dafny.Program dafnyProgram; private Bpl.Program boogieProgram; public DafnyHelper(string fname, string source) { this.fname = fname; this.source = source; - this.errors = new Dafny.Errors(); + this.reporter = new Dafny.ConsoleErrorReporter(); } public bool Verify() { @@ -47,10 +47,10 @@ namespace Microsoft.Dafny { private bool Parse() { Dafny.ModuleDecl module = new Dafny.LiteralModuleDecl(new Dafny.DefaultModuleDecl(), null); Dafny.BuiltIns builtIns = new Dafny.BuiltIns(); - var success = (Dafny.Parser.Parse(source, fname, fname, module, builtIns, errors) == 0 && - Dafny.Main.ParseIncludes(module, builtIns, new List(), errors) == null); + var success = (Dafny.Parser.Parse(source, fname, fname, module, builtIns, new Dafny.Errors(reporter)) == 0 && + Dafny.Main.ParseIncludes(module, builtIns, new List(), new Dafny.Errors(reporter)) == null); if (success) { - dafnyProgram = new Dafny.Program(fname, module, builtIns); + dafnyProgram = new Dafny.Program(fname, module, builtIns, reporter); } return success; } @@ -58,11 +58,11 @@ namespace Microsoft.Dafny { private bool Resolve() { var resolver = new Dafny.Resolver(dafnyProgram); resolver.ResolveProgram(dafnyProgram); - return resolver.ErrorCount == 0; + return reporter.Count(ErrorLevel.Error) == 0; } private bool Translate() { - var translator = new Dafny.Translator() { InsertChecksums = true, UniqueIdPrefix = null }; //FIXME check if null is OK for UniqueIdPrefix + var translator = new Dafny.Translator(reporter) { InsertChecksums = true, UniqueIdPrefix = null }; //FIXME check if null is OK for UniqueIdPrefix boogieProgram = translator.Translate(dafnyProgram); // FIXME how are translation errors reported? return true; } @@ -74,7 +74,8 @@ namespace Microsoft.Dafny { ExecutionEngine.CoalesceBlocks(boogieProgram); ExecutionEngine.Inline(boogieProgram); - switch (ExecutionEngine.InferAndVerify(boogieProgram, new PipelineStatistics(), "ServerProgram", null, DateTime.UtcNow.Ticks.ToString())) { // FIXME check if null is ok for error delegate + //FIXME Could capture errors instead of printing them (pass a delegate instead of null) + switch (ExecutionEngine.InferAndVerify(boogieProgram, new PipelineStatistics(), "ServerProgram", null, DateTime.UtcNow.Ticks.ToString())) { case PipelineOutcome.Done: case PipelineOutcome.VerificationCompleted: return true; -- cgit v1.2.3 From 8ede9fda35767f083899940886b69f53640891c9 Mon Sep 17 00:00:00 2001 From: Clément Pit--Claudel Date: Thu, 27 Aug 2015 18:59:10 -0700 Subject: Look for z3 in Binaries/z3/bin (but keep the vendored version for convenience) Dafny now first looks for a z3 binary in z3/bin, and if it can't find one it looks for one in Binaries/z3.exe (mostly for backwards-compatibility with already set-up source installations). --- Binaries/z3 | Bin 16438468 -> 0 bytes Source/Dafny/DafnyOptions.cs | 37 ++++++++++++++++++++++++++++----- Source/Dafny/Reporting.cs | 2 +- Source/DafnyDriver/DafnyDriver.cs | 14 ++++++------- Source/DafnyServer/DafnyHelper.cs | 5 ++++- Source/DafnyServer/Utilities.cs | 4 ++-- Source/DafnyServer/VerificationTask.cs | 3 +-- 7 files changed, 47 insertions(+), 18 deletions(-) delete mode 100755 Binaries/z3 (limited to 'Source/DafnyDriver/DafnyDriver.cs') diff --git a/Binaries/z3 b/Binaries/z3 deleted file mode 100755 index 7c60feb4..00000000 Binary files a/Binaries/z3 and /dev/null differ diff --git a/Source/Dafny/DafnyOptions.cs b/Source/Dafny/DafnyOptions.cs index 1986ea6d..08e53d5c 100644 --- a/Source/Dafny/DafnyOptions.cs +++ b/Source/Dafny/DafnyOptions.cs @@ -9,8 +9,11 @@ namespace Microsoft.Dafny { public class DafnyOptions : Bpl.CommandLineOptions { - public DafnyOptions() + private ErrorReporter errorReporter; + + public DafnyOptions(ErrorReporter errorReporter = null) : base("Dafny", "Dafny program verifier") { + this.errorReporter = errorReporter; SetZ3ExecutableName(); } @@ -257,13 +260,37 @@ namespace Microsoft.Dafny // TODO: provide attribute help here } + + /// + /// Dafny comes with it's own copy of z3, to save new users the trouble of having to install extra dependency. + /// For this to work, Dafny makes the Z3ExecutablePath point to the path were Z3 is put by our release script. + /// For developers though (and people getting this from source), it's convenient to be able to run right away, + /// so we vendor a Windows version. + /// private void SetZ3ExecutableName() { var platform = (int)System.Environment.OSVersion.Platform; - var isLinux = platform == 4 || platform == 128; // http://www.mono-project.com/docs/faq/technical/ - //TODO should we also vendor an OSX build? - var binDir = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location); - Z3ExecutablePath = System.IO.Path.Combine(binDir, isLinux ? "z3" : "z3.exe"); + // http://www.mono-project.com/docs/faq/technical/ + var isUnix = platform == 4 || platform == 128; + + var z3binName = isUnix ? "z3" : "z3.exe"; + var dafnyBinDir = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location); + var z3BinDir = System.IO.Path.Combine(dafnyBinDir, "z3", "bin"); + var z3BinPath = System.IO.Path.Combine(z3BinDir, z3binName); + + if (!System.IO.File.Exists(z3BinPath) && !isUnix) { + // This is most likely a Windows user running from source without downloading z3 + // separately; this is ok, since we vendor z3.exe. + z3BinPath = System.IO.Path.Combine(dafnyBinDir, z3binName); + } + + if (!System.IO.File.Exists(z3BinPath) && errorReporter != null) { + var tok = new Bpl.Token(1, 1) { filename = "*** " }; + errorReporter.Warning(MessageSource.Other, tok, "Could not find '{0}' in '{1}'.{2}Downloading and extracting a Z3 distribution to Dafny's 'Binaries' folder would solve this issue; for now, we'll rely on Boogie to find Z3.", + z3binName, z3BinDir, System.Environment.NewLine); + } else { + Z3ExecutablePath = z3BinPath; + } } public override void Usage() { diff --git a/Source/Dafny/Reporting.cs b/Source/Dafny/Reporting.cs index 4cfbf20e..760392ca 100644 --- a/Source/Dafny/Reporting.cs +++ b/Source/Dafny/Reporting.cs @@ -143,7 +143,7 @@ namespace Microsoft.Dafny { } public override bool Message(MessageSource source, ErrorLevel level, IToken tok, string msg) { - if (base.Message(source, level, tok, msg) && (DafnyOptions.O.PrintTooltips || level != ErrorLevel.Info)) { + if (base.Message(source, level, tok, msg) && ((DafnyOptions.O != null && DafnyOptions.O.PrintTooltips) || level != ErrorLevel.Info)) { // Extra indent added to make it easier to distinguish multiline error messages for clients that rely on the CLI msg = msg.Replace(Environment.NewLine, Environment.NewLine + " "); diff --git a/Source/DafnyDriver/DafnyDriver.cs b/Source/DafnyDriver/DafnyDriver.cs index 4b5ae8d8..c45d66fc 100644 --- a/Source/DafnyDriver/DafnyDriver.cs +++ b/Source/DafnyDriver/DafnyDriver.cs @@ -40,10 +40,11 @@ namespace Microsoft.Dafny public static int ThreadMain(string[] args) { Contract.Requires(cce.NonNullElements(args)); - + + ErrorReporter reporter = new ConsoleErrorReporter(); ExecutionEngine.printer = new DafnyConsolePrinter(); // For boogie errors - DafnyOptions.Install(new DafnyOptions()); + DafnyOptions.Install(new DafnyOptions(reporter)); ExitValue exitValue = ExitValue.VERIFIED; CommandLineOptions.Clo.RunningBoogieFromCommandLine = true; @@ -92,7 +93,7 @@ namespace Microsoft.Dafny goto END; } } - exitValue = ProcessFiles(CommandLineOptions.Clo.Files); + exitValue = ProcessFiles(CommandLineOptions.Clo.Files, reporter); END: if (CommandLineOptions.Clo.XmlSink != null) { @@ -112,7 +113,7 @@ namespace Microsoft.Dafny } - static ExitValue ProcessFiles(IList/*!*/ fileNames, bool lookForSnapshots = true, string programId = null) + static ExitValue ProcessFiles(IList/*!*/ fileNames, ErrorReporter reporter, bool lookForSnapshots = true, string programId = null) { Contract.Requires(cce.NonNullElements(fileNames)); @@ -128,7 +129,7 @@ namespace Microsoft.Dafny { Console.WriteLine(); Console.WriteLine("-------------------- {0} --------------------", f); - var ev = ProcessFiles(new List { f }, lookForSnapshots, f); + var ev = ProcessFiles(new List { f }, reporter, lookForSnapshots, f); if (exitValue != ev && ev != ExitValue.VERIFIED) { exitValue = ev; @@ -142,7 +143,7 @@ namespace Microsoft.Dafny var snapshotsByVersion = ExecutionEngine.LookForSnapshots(fileNames); foreach (var s in snapshotsByVersion) { - var ev = ProcessFiles(new List(s), false, programId); + var ev = ProcessFiles(new List(s), reporter, false, programId); if (exitValue != ev && ev != ExitValue.VERIFIED) { exitValue = ev; @@ -153,7 +154,6 @@ namespace Microsoft.Dafny using (XmlFileScope xf = new XmlFileScope(CommandLineOptions.Clo.XmlSink, fileNames[fileNames.Count-1])) { Dafny.Program dafnyProgram; - ErrorReporter reporter = new ConsoleErrorReporter(); string programName = fileNames.Count == 1 ? fileNames[0] : "the program"; string err = Dafny.Main.ParseCheck(fileNames, programName, reporter, out dafnyProgram); if (err != null) { diff --git a/Source/DafnyServer/DafnyHelper.cs b/Source/DafnyServer/DafnyHelper.cs index 3204fdb3..e54e2b48 100644 --- a/Source/DafnyServer/DafnyHelper.cs +++ b/Source/DafnyServer/DafnyHelper.cs @@ -29,18 +29,21 @@ namespace Microsoft.Dafny { class DafnyHelper { private string fname; private string source; + private string[] args; private readonly Dafny.ErrorReporter reporter; private Dafny.Program dafnyProgram; private Bpl.Program boogieProgram; - public DafnyHelper(string fname, string source) { + public DafnyHelper(string[] args, string fname, string source) { + this.args = args; this.fname = fname; this.source = source; this.reporter = new Dafny.ConsoleErrorReporter(); } public bool Verify() { + ServerUtils.ApplyArgs(args, reporter); return Parse() && Resolve() && Translate() && Boogie(); } diff --git a/Source/DafnyServer/Utilities.cs b/Source/DafnyServer/Utilities.cs index 59b3abb9..5e2c6f96 100644 --- a/Source/DafnyServer/Utilities.cs +++ b/Source/DafnyServer/Utilities.cs @@ -43,8 +43,8 @@ namespace Microsoft.Dafny { } } - internal static void ApplyArgs(string[] args) { - Dafny.DafnyOptions.Install(new Dafny.DafnyOptions()); + internal static void ApplyArgs(string[] args, ErrorReporter reporter) { + Dafny.DafnyOptions.Install(new Dafny.DafnyOptions(reporter)); Dafny.DafnyOptions.O.ProverKillTime = 15; //This is just a default; it can be overriden if (CommandLineOptions.Clo.Parse(args)) { diff --git a/Source/DafnyServer/VerificationTask.cs b/Source/DafnyServer/VerificationTask.cs index a00688b1..eb740e70 100644 --- a/Source/DafnyServer/VerificationTask.cs +++ b/Source/DafnyServer/VerificationTask.cs @@ -52,8 +52,7 @@ namespace Microsoft.Dafny { } internal void Run() { - ServerUtils.ApplyArgs(args); - new DafnyHelper(filename, ProgramSource).Verify(); + new DafnyHelper(args, filename, ProgramSource).Verify(); } } } -- cgit v1.2.3 From 69ed5bac5efbc0ac64f26b6dadf81bcfec9a0b5b Mon Sep 17 00:00:00 2001 From: wuestholz Date: Tue, 29 Sep 2015 17:45:10 +0200 Subject: Fix the build. --- Source/DafnyDriver/DafnyDriver.cs | 6 +++--- Source/DafnyServer/DafnyServer.csproj | 13 ++++++++----- 2 files changed, 11 insertions(+), 8 deletions(-) (limited to 'Source/DafnyDriver/DafnyDriver.cs') diff --git a/Source/DafnyDriver/DafnyDriver.cs b/Source/DafnyDriver/DafnyDriver.cs index c45d66fc..8282edc7 100644 --- a/Source/DafnyDriver/DafnyDriver.cs +++ b/Source/DafnyDriver/DafnyDriver.cs @@ -226,8 +226,8 @@ namespace Microsoft.Dafny stats = new PipelineStatistics(); LinearTypeChecker ltc; - MoverTypeChecker mtc; - PipelineOutcome oc = ExecutionEngine.ResolveAndTypecheck(program, bplFileName, out ltc, out mtc); + CivlTypeChecker ctc; + PipelineOutcome oc = ExecutionEngine.ResolveAndTypecheck(program, bplFileName, out ltc, out ctc); switch (oc) { case PipelineOutcome.Done: return oc; @@ -244,7 +244,7 @@ namespace Microsoft.Dafny fileNames.Add(bplFileName); Bpl.Program reparsedProgram = ExecutionEngine.ParseBoogieProgram(fileNames, true); if (reparsedProgram != null) { - ExecutionEngine.ResolveAndTypecheck(reparsedProgram, bplFileName, out ltc, out mtc); + ExecutionEngine.ResolveAndTypecheck(reparsedProgram, bplFileName, out ltc, out ctc); } } return oc; diff --git a/Source/DafnyServer/DafnyServer.csproj b/Source/DafnyServer/DafnyServer.csproj index 1a256f5f..af262fc3 100644 --- a/Source/DafnyServer/DafnyServer.csproj +++ b/Source/DafnyServer/DafnyServer.csproj @@ -1,4 +1,4 @@ - + @@ -84,9 +84,6 @@ - - ..\..\Binaries\DafnyPipeline.dll - @@ -99,6 +96,12 @@ + + + {fe44674a-1633-4917-99f4-57635e6fa740} + DafnyPipeline + + - + \ No newline at end of file -- cgit v1.2.3 From 2b7d31bb3e0276028a8bc50c4933ea60fed5fb60 Mon Sep 17 00:00:00 2001 From: qunyanm Date: Wed, 4 Nov 2015 10:36:54 -0800 Subject: Fix issue89. Copy the out param to a local before use it in an anonymous method that is generated by LetExpr. Change the compiler so that each stmt writes to its own buffer before add it to the program's buffer so that we can insert the above mentioned copy instruction before the stmt. --- Source/Dafny/Compiler.cs | 1151 +++++++++++++++++++------------------ Source/DafnyDriver/DafnyDriver.cs | 4 +- Test/dafny4/Bug89.dfy | 15 + Test/dafny4/Bug89.dfy.expect | 6 + 4 files changed, 610 insertions(+), 566 deletions(-) create mode 100644 Test/dafny4/Bug89.dfy create mode 100644 Test/dafny4/Bug89.dfy.expect (limited to 'Source/DafnyDriver/DafnyDriver.cs') diff --git a/Source/Dafny/Compiler.cs b/Source/Dafny/Compiler.cs index aa4ca3ec..f992d6c0 100644 --- a/Source/Dafny/Compiler.cs +++ b/Source/Dafny/Compiler.cs @@ -14,18 +14,11 @@ using System.Text; namespace Microsoft.Dafny { public class Compiler { - public Compiler(TextWriter wr) { - Contract.Requires(wr != null); - this.wr = wr; + public Compiler() { + } - [ContractInvariantMethod] - void ObjectInvariant() - { - Contract.Invariant(wr!=null); - } - - TextWriter wr; + StringBuilder copyInstrWriter = new StringBuilder(); // a buffer that stores copy instructions generated by letExpr that uses out param. Method enclosingMethod; // non-null when a method body is being translated FreshIdGenerator idGenerator = new FreshIdGenerator(); @@ -50,7 +43,7 @@ namespace Microsoft.Dafny { public int ErrorCount; public TextWriter ErrorWriter = Console.Out; - void Error(string msg, params object[] args) { + void Error(string msg, TextWriter wr, params object[] args) { Contract.Requires(msg != null); Contract.Requires(args != null); @@ -60,7 +53,7 @@ namespace Microsoft.Dafny { ErrorCount++; } - void ReadRuntimeSystem() { + void ReadRuntimeSystem(TextWriter wr) { string codebase = cce.NonNull( System.IO.Path.GetDirectoryName(cce.NonNull(System.Reflection.Assembly.GetExecutingAssembly().Location))); string path = System.IO.Path.Combine(codebase, "DafnyRuntime.cs"); using (TextReader rd = new StreamReader(new FileStream(path, System.IO.FileMode.Open, System.IO.FileAccess.Read))) @@ -75,16 +68,16 @@ namespace Microsoft.Dafny { } readonly int IndentAmount = 2; - void Indent(int ind) { + void Indent(int ind, TextWriter wr) { Contract.Requires(0 <= ind); string spaces = " "; for (; spaces.Length < ind; ind -= spaces.Length) { wr.Write(spaces); } - wr.Write(spaces.Substring(0, ind)); + wr.Write(spaces.Substring(0, ind)); } - public void Compile(Program program) { + public void Compile(Program program, TextWriter wr) { Contract.Requires(program != null); wr.WriteLine("// Dafny program {0} compiled into C#", program.Name); wr.WriteLine("// To recompile, use 'csc' with: /r:System.Numerics.dll"); @@ -92,8 +85,8 @@ namespace Microsoft.Dafny { wr.WriteLine("// You might also want to include compiler switches like:"); wr.WriteLine("// /debug /nowarn:0164 /nowarn:0219"); wr.WriteLine(); - ReadRuntimeSystem(); - CompileBuiltIns(program.BuiltIns); + ReadRuntimeSystem(wr); + CompileBuiltIns(program.BuiltIns, wr); foreach (ModuleDefinition m in program.CompileModules) { if (m.IsAbstract) { @@ -117,33 +110,33 @@ namespace Microsoft.Dafny { wr.WriteLine(); if (d is OpaqueTypeDecl) { var at = (OpaqueTypeDecl)d; - Error("Opaque type ('{0}') cannot be compiled", at.FullName); + Error("Opaque type ('{0}') cannot be compiled", wr, at.FullName); } else if (d is TypeSynonymDecl) { // do nothing, just bypass type synonyms in the compiler } else if (d is NewtypeDecl) { var nt = (NewtypeDecl)d; - Indent(indent); + Indent(indent, wr); wr.WriteLine("public class @{0} {{", nt.CompileName); if (nt.NativeType != null) { - Indent(indent + IndentAmount); + Indent(indent + IndentAmount, wr); wr.WriteLine("public static System.Collections.Generic.IEnumerable<{0}> IntegerRange(BigInteger lo, BigInteger hi) {{", nt.NativeType.Name); - Indent(indent + 2 * IndentAmount); + Indent(indent + 2 * IndentAmount, wr); wr.WriteLine("for (var j = lo; j < hi; j++) {{ yield return ({0})j; }}", nt.NativeType.Name); - Indent(indent + IndentAmount); + Indent(indent + IndentAmount, wr); wr.WriteLine("}"); } - Indent(indent); + Indent(indent, wr); wr.WriteLine("}"); } else if (d is DatatypeDecl) { var dt = (DatatypeDecl)d; - Indent(indent); + Indent(indent, wr); wr.Write("public abstract class Base_{0}", dt.CompileName); if (dt.TypeArgs.Count != 0) { wr.Write("<{0}>", TypeParameters(dt.TypeArgs)); } wr.WriteLine(" { }"); - CompileDatatypeConstructors(dt, indent); - CompileDatatypeStruct(dt, indent); + CompileDatatypeConstructors(dt, indent, wr); + CompileDatatypeStruct(dt, indent, wr); } else if (d is IteratorDecl) { var iter = (IteratorDecl)d; // An iterator is compiled as follows: @@ -169,7 +162,7 @@ namespace Microsoft.Dafny { // } // } - Indent(indent); + Indent(indent, wr); wr.Write("public class @{0}", iter.CompileName); if (iter.TypeArgs.Count != 0) { wr.Write("<{0}>", TypeParameters(iter.TypeArgs)); @@ -181,58 +174,58 @@ namespace Microsoft.Dafny { foreach (var member in iter.Members) { var f = member as Field; if (f != null && !f.IsGhost) { - Indent(ind); - wr.WriteLine("public {0} @{1} = {2};", TypeName(f.Type), f.CompileName, DefaultValue(f.Type)); + Indent(ind, wr); + wr.WriteLine("public {0} @{1} = {2};", TypeName(f.Type, wr), f.CompileName, DefaultValue(f.Type, wr)); } else if (member is Constructor) { Contract.Assert(ct == null); // we're expecting just one constructor ct = (Constructor)member; } } Contract.Assert(ct != null); // we do expect a constructor - Indent(ind); wr.WriteLine("System.Collections.Generic.IEnumerator __iter;"); + Indent(ind, wr); wr.WriteLine("System.Collections.Generic.IEnumerator __iter;"); // here's the initializer method - Indent(ind); wr.Write("public void @{0}(", ct.CompileName); + Indent(ind, wr); wr.Write("public void @{0}(", ct.CompileName); string sep = ""; foreach (var p in ct.Ins) { if (!p.IsGhost) { // here we rely on the parameters and the corresponding fields having the same names - wr.Write("{0}{1} @{2}", sep, TypeName(p.Type), p.CompileName); + wr.Write("{0}{1} @{2}", sep, TypeName(p.Type, wr), p.CompileName); sep = ", "; } } wr.WriteLine(") {"); foreach (var p in ct.Ins) { if (!p.IsGhost) { - Indent(ind + IndentAmount); + Indent(ind + IndentAmount, wr); wr.WriteLine("this.@{0} = @{0};", p.CompileName); } } - Indent(ind + IndentAmount); wr.WriteLine("__iter = TheIterator();"); - Indent(ind); wr.WriteLine("}"); + Indent(ind + IndentAmount, wr); wr.WriteLine("__iter = TheIterator();"); + Indent(ind, wr); wr.WriteLine("}"); // here are the enumerator methods - Indent(ind); wr.WriteLine("public void MoveNext(out bool more) { more = __iter.MoveNext(); }"); - Indent(ind); wr.WriteLine("private System.Collections.Generic.IEnumerator TheIterator() {"); + Indent(ind, wr); wr.WriteLine("public void MoveNext(out bool more) { more = __iter.MoveNext(); }"); + Indent(ind, wr); wr.WriteLine("private System.Collections.Generic.IEnumerator TheIterator() {"); if (iter.Body == null) { - Error("Iterator {0} has no body", iter.FullName); + Error("Iterator {0} has no body", wr, iter.FullName); } else { - TrStmt(iter.Body, ind + IndentAmount); + wr.Write(TrStmt(iter.Body, ind + IndentAmount).ToString()); } - Indent(ind + IndentAmount); wr.WriteLine("yield break;"); - Indent(ind); wr.WriteLine("}"); + Indent(ind + IndentAmount, wr); wr.WriteLine("yield break;"); + Indent(ind, wr); wr.WriteLine("}"); // end of the class - Indent(indent); wr.WriteLine("}"); + Indent(indent, wr); wr.WriteLine("}"); } else if (d is TraitDecl) { //writing the trait var trait = (TraitDecl)d; - Indent(indent); + Indent(indent, wr); wr.Write("public interface @{0}", trait.CompileName); wr.WriteLine(" {"); - CompileClassMembers(trait, false, indent + IndentAmount); - Indent(indent); wr.WriteLine("}"); + CompileClassMembers(trait, false, indent + IndentAmount, wr); + Indent(indent, wr); wr.WriteLine("}"); //writing the _Companion class List members = new List(); @@ -252,27 +245,27 @@ namespace Microsoft.Dafny { } } } - Indent(indent); + Indent(indent, wr); wr.Write("public class @_Companion_{0}", trait.CompileName); wr.WriteLine(" {"); - CompileClassMembers(trait, true, indent + IndentAmount); - Indent(indent); wr.WriteLine("}"); + CompileClassMembers(trait, true, indent + IndentAmount, wr); + Indent(indent, wr); wr.WriteLine("}"); } else if (d is ClassDecl) { var cl = (ClassDecl)d; - Indent(indent); + Indent(indent, wr); wr.Write("public class @{0}", cl.CompileName); if (cl.TypeArgs.Count != 0) { wr.Write("<{0}>", TypeParameters(cl.TypeArgs)); } string sep = " : "; foreach (var trait in cl.TraitsTyp) { - wr.Write("{0}{1}", sep, TypeName(trait)); + wr.Write("{0}{1}", sep, TypeName(trait, wr)); sep = ", "; } wr.WriteLine(" {"); - CompileClassMembers(cl, false, indent+IndentAmount); - Indent(indent); wr.WriteLine("}"); + CompileClassMembers(cl, false, indent+IndentAmount, wr); + Indent(indent, wr); wr.WriteLine("}"); } else if (d is ModuleDecl) { // nop } else { Contract.Assert(false); } @@ -283,15 +276,15 @@ namespace Microsoft.Dafny { } } - void CompileBuiltIns(BuiltIns builtIns) { + void CompileBuiltIns(BuiltIns builtIns, TextWriter wr) { wr.WriteLine("namespace Dafny {"); - Indent(IndentAmount); + Indent(IndentAmount, wr); wr.WriteLine("public partial class Helpers {"); foreach (var decl in builtIns.SystemModule.TopLevelDecls) { if (decl is ArrayClassDecl) { int dims = ((ArrayClassDecl)decl).Dims; // public static T[,] InitNewArray2(BigInteger size0, BigInteger size1) { - Indent(3 * IndentAmount); + Indent(3 * IndentAmount, wr); wr.Write("public static T["); RepeatWrite(wr, dims, "", ","); wr.Write("] InitNewArray{0}(", dims); @@ -299,52 +292,52 @@ namespace Microsoft.Dafny { wr.WriteLine(") {"); // int s0 = (int)size0; for (int i = 0; i < dims; i++) { - Indent(4 * IndentAmount); + Indent(4 * IndentAmount, wr); wr.WriteLine("int s{0} = (int)size{0};", i); } // T[,] a = new T[s0, s1]; - Indent(4 * IndentAmount); + Indent(4 * IndentAmount, wr); wr.Write("T["); RepeatWrite(wr, dims, "", ","); wr.Write("] a = new T["); RepeatWrite(wr, dims, "s{0}", ","); wr.WriteLine("];"); // BigInteger[,] b = a as BigInteger[,]; - Indent(4 * IndentAmount); + Indent(4 * IndentAmount, wr); wr.Write("BigInteger["); RepeatWrite(wr, dims, "", ","); wr.Write("] b = a as BigInteger["); RepeatWrite(wr, dims, "", ","); wr.WriteLine("];"); // if (b != null) { - Indent(4 * IndentAmount); + Indent(4 * IndentAmount, wr); wr.WriteLine("if (b != null) {"); // BigInteger z = new BigInteger(0); - Indent(5 * IndentAmount); + Indent(5 * IndentAmount, wr); wr.WriteLine("BigInteger z = new BigInteger(0);"); // for (int i0 = 0; i0 < s0; i0++) // for (int i1 = 0; i1 < s1; i1++) for (int i = 0; i < dims; i++) { - Indent((5+i) * IndentAmount); + Indent((5+i) * IndentAmount, wr); wr.WriteLine("for (int i{0} = 0; i{0} < s{0}; i{0}++)", i); } // b[i0,i1] = z; - Indent((5+dims) * IndentAmount); + Indent((5+dims) * IndentAmount, wr); wr.Write("b["); RepeatWrite(wr, dims, "i{0}", ","); wr.WriteLine("] = z;"); // } - Indent(4 * IndentAmount); + Indent(4 * IndentAmount, wr); wr.WriteLine("}"); // return a; - Indent(4 * IndentAmount); + Indent(4 * IndentAmount, wr); wr.WriteLine("return a;"); // } - Indent(3 * IndentAmount); + Indent(3 * IndentAmount, wr); wr.WriteLine("}"); // end of method } } - Indent(IndentAmount); + Indent(IndentAmount, wr); wr.WriteLine("}"); // end of class Helpers wr.WriteLine("}"); // end of namespace } @@ -359,7 +352,7 @@ namespace Microsoft.Dafny { } } - void CompileDatatypeConstructors(DatatypeDecl dt, int indent) + void CompileDatatypeConstructors(DatatypeDecl dt, int indent, TextWriter wr) { Contract.Requires(dt != null); @@ -372,20 +365,20 @@ namespace Microsoft.Dafny { // public Dt__Lazy(Computer c) { this.c = c; } // public Base_Dt Get() { return c(); } // } - Indent(indent); + Indent(indent, wr); wr.WriteLine("public class {0}__Lazy{1} : Base_{0}{1} {{", dt.CompileName, typeParams); int ind = indent + IndentAmount; - Indent(ind); + Indent(ind, wr); wr.WriteLine("public delegate Base_{0}{1} Computer();", dt.CompileName, typeParams); - Indent(ind); + Indent(ind, wr); wr.WriteLine("public delegate Computer ComputerComputer();"); - Indent(ind); + Indent(ind, wr); wr.WriteLine("Computer c;"); - Indent(ind); + Indent(ind, wr); wr.WriteLine("public {0}__Lazy(Computer c) {{ this.c = c; }}", dt.CompileName); - Indent(ind); + Indent(ind, wr); wr.WriteLine("public Base_{0}{1} Get() {{ return c(); }}", dt.CompileName, typeParams); - Indent(indent); + Indent(indent, wr); wr.WriteLine("}"); } @@ -407,7 +400,7 @@ namespace Microsoft.Dafny { // // ... // } // } - Indent(indent); + Indent(indent, wr); wr.Write("public class {0}", DtCtorDeclarationName(ctor, dt.TypeArgs)); wr.WriteLine(" : Base_{0}{1} {{", dt.CompileName, typeParams); int ind = indent + IndentAmount; @@ -415,32 +408,32 @@ namespace Microsoft.Dafny { int i = 0; foreach (Formal arg in ctor.Formals) { if (!arg.IsGhost) { - Indent(ind); - wr.WriteLine("public readonly {0} @{1};", TypeName(arg.Type), FormalName(arg, i)); + Indent(ind, wr); + wr.WriteLine("public readonly {0} @{1};", TypeName(arg.Type, wr), FormalName(arg, i)); i++; } } - Indent(ind); + Indent(ind, wr); wr.Write("public {0}(", DtCtorDeclartionName(ctor)); - WriteFormals("", ctor.Formals); + WriteFormals("", ctor.Formals, wr); wr.WriteLine(") {"); i = 0; foreach (Formal arg in ctor.Formals) { if (!arg.IsGhost) { - Indent(ind + IndentAmount); + Indent(ind + IndentAmount, wr); wr.WriteLine("this.@{0} = @{0};", FormalName(arg, i)); i++; } } - Indent(ind); wr.WriteLine("}"); + Indent(ind, wr); wr.WriteLine("}"); // Equals method - Indent(ind); wr.WriteLine("public override bool Equals(object other) {"); - Indent(ind + IndentAmount); + Indent(ind, wr); wr.WriteLine("public override bool Equals(object other) {"); + Indent(ind + IndentAmount, wr); wr.Write("var oth = other as {0}", DtCtorName(ctor, dt.TypeArgs)); wr.WriteLine(";"); - Indent(ind + IndentAmount); + Indent(ind + IndentAmount, wr); wr.Write("return oth != null"); i = 0; foreach (Formal arg in ctor.Formals) { @@ -455,56 +448,56 @@ namespace Microsoft.Dafny { } } wr.WriteLine(";"); - Indent(ind); wr.WriteLine("}"); + Indent(ind, wr); wr.WriteLine("}"); // GetHashCode method (Uses the djb2 algorithm) - Indent(ind); wr.WriteLine("public override int GetHashCode() {"); - Indent(ind + IndentAmount); wr.WriteLine("ulong hash = 5381;"); - Indent(ind + IndentAmount); wr.WriteLine("hash = ((hash << 5) + hash) + {0};", constructorIndex); + Indent(ind, wr); wr.WriteLine("public override int GetHashCode() {"); + Indent(ind + IndentAmount, wr); wr.WriteLine("ulong hash = 5381;"); + Indent(ind + IndentAmount, wr); wr.WriteLine("hash = ((hash << 5) + hash) + {0};", constructorIndex); i = 0; foreach (Formal arg in ctor.Formals) { if (!arg.IsGhost) { string nm = FormalName(arg, i); - Indent(ind + IndentAmount); wr.WriteLine("hash = ((hash << 5) + hash) + ((ulong)this.@{0}.GetHashCode());", nm); + Indent(ind + IndentAmount, wr); wr.WriteLine("hash = ((hash << 5) + hash) + ((ulong)this.@{0}.GetHashCode());", nm); i++; } } - Indent(ind + IndentAmount); wr.WriteLine("return (int) hash;"); - Indent(ind); wr.WriteLine("}"); + Indent(ind + IndentAmount, wr); wr.WriteLine("return (int) hash;"); + Indent(ind, wr); wr.WriteLine("}"); if (dt is IndDatatypeDecl) { - Indent(ind); wr.WriteLine("public override string ToString() {"); + Indent(ind, wr); wr.WriteLine("public override string ToString() {"); string nm; if (dt is TupleTypeDecl) { nm = ""; } else { nm = (dt.Module.IsDefaultModule ? "" : dt.Module.CompileName + ".") + dt.CompileName + "." + ctor.CompileName; } - Indent(ind + IndentAmount); wr.WriteLine("string s = \"{0}\";", nm); + Indent(ind + IndentAmount, wr); wr.WriteLine("string s = \"{0}\";", nm); if (ctor.Formals.Count != 0) { - Indent(ind + IndentAmount); wr.WriteLine("s += \"(\";"); + Indent(ind + IndentAmount, wr); wr.WriteLine("s += \"(\";"); i = 0; foreach (var arg in ctor.Formals) { if (!arg.IsGhost) { if (i != 0) { - Indent(ind + IndentAmount); wr.WriteLine("s += \", \";"); + Indent(ind + IndentAmount, wr); wr.WriteLine("s += \", \";"); } - Indent(ind + IndentAmount); wr.WriteLine("s += @{0}.ToString();", FormalName(arg, i)); + Indent(ind + IndentAmount, wr); wr.WriteLine("s += @{0}.ToString();", FormalName(arg, i)); i++; } } - Indent(ind + IndentAmount); wr.WriteLine("s += \")\";"); + Indent(ind + IndentAmount, wr); wr.WriteLine("s += \")\";"); } - Indent(ind + IndentAmount); wr.WriteLine("return s;"); - Indent(ind); wr.WriteLine("}"); + Indent(ind + IndentAmount, wr); wr.WriteLine("return s;"); + Indent(ind, wr); wr.WriteLine("}"); } - Indent(indent); wr.WriteLine("}"); + Indent(indent, wr); wr.WriteLine("}"); } constructorIndex++; } - void CompileDatatypeStruct(DatatypeDecl dt, int indent) { + void CompileDatatypeStruct(DatatypeDecl dt, int indent, TextWriter wr) { Contract.Requires(dt != null); // public struct Dt : IDatatype{ @@ -548,46 +541,46 @@ namespace Microsoft.Dafny { DtT += DtT_TypeArgs; } - Indent(indent); + Indent(indent, wr); wr.WriteLine("public struct @{0} {{", DtT); int ind = indent + IndentAmount; - Indent(ind); + Indent(ind, wr); wr.WriteLine("Base_{0} _d;", DtT); - Indent(ind); + Indent(ind, wr); wr.WriteLine("public Base_{0} _D {{", DtT); - Indent(ind + IndentAmount); + Indent(ind + IndentAmount, wr); wr.WriteLine("get {"); - Indent(ind + 2 * IndentAmount); + Indent(ind + 2 * IndentAmount, wr); wr.WriteLine("if (_d == null) {"); - Indent(ind + 3 * IndentAmount); + Indent(ind + 3 * IndentAmount, wr); wr.WriteLine("_d = Default;"); if (dt is CoDatatypeDecl) { string typeParams = dt.TypeArgs.Count == 0 ? "" : string.Format("<{0}>", TypeParameters(dt.TypeArgs)); - Indent(ind + 2 * IndentAmount); + Indent(ind + 2 * IndentAmount, wr); wr.WriteLine("}} else if (_d is {0}__Lazy{1}) {{", dt.CompileName, typeParams); - Indent(ind + 3 * IndentAmount); + Indent(ind + 3 * IndentAmount, wr); wr.WriteLine("_d = (({0}__Lazy{1})_d).Get();", dt.CompileName, typeParams); } - Indent(ind + 2 * IndentAmount); wr.WriteLine("}"); - Indent(ind + 2 * IndentAmount); wr.WriteLine("return _d;"); - Indent(ind + IndentAmount); wr.WriteLine("}"); - Indent(ind); wr.WriteLine("}"); + Indent(ind + 2 * IndentAmount, wr); wr.WriteLine("}"); + Indent(ind + 2 * IndentAmount, wr); wr.WriteLine("return _d;"); + Indent(ind + IndentAmount, wr); wr.WriteLine("}"); + Indent(ind, wr); wr.WriteLine("}"); - Indent(ind); + Indent(ind, wr); wr.WriteLine("public @{0}(Base_{1} d) {{ this._d = d; }}", dt.CompileName, DtT); - Indent(ind); + Indent(ind, wr); wr.WriteLine("static Base_{0} theDefault;", DtT); - Indent(ind); + Indent(ind, wr); wr.WriteLine("public static Base_{0} Default {{", DtT); - Indent(ind + IndentAmount); + Indent(ind + IndentAmount, wr); wr.WriteLine("get {"); - Indent(ind + 2 * IndentAmount); + Indent(ind + 2 * IndentAmount, wr); wr.WriteLine("if (theDefault == null) {"); - Indent(ind + 3 * IndentAmount); + Indent(ind + 3 * IndentAmount, wr); wr.Write("theDefault = "); DatatypeCtor defaultCtor; @@ -601,55 +594,55 @@ namespace Microsoft.Dafny { string sep = ""; foreach (Formal f in defaultCtor.Formals) { if (!f.IsGhost) { - wr.Write("{0}{1}", sep, DefaultValue(f.Type)); + wr.Write("{0}{1}", sep, DefaultValue(f.Type, wr)); sep = ", "; } } wr.Write(")"); wr.WriteLine(";"); - Indent(ind + 2 * IndentAmount); + Indent(ind + 2 * IndentAmount, wr); wr.WriteLine("}"); - Indent(ind + 2 * IndentAmount); + Indent(ind + 2 * IndentAmount, wr); wr.WriteLine("return theDefault;"); - Indent(ind + IndentAmount); wr.WriteLine("}"); + Indent(ind + IndentAmount, wr); wr.WriteLine("}"); - Indent(ind); wr.WriteLine("}"); + Indent(ind, wr); wr.WriteLine("}"); - Indent(ind); wr.WriteLine("public override bool Equals(object other) {"); - Indent(ind + IndentAmount); + Indent(ind, wr); wr.WriteLine("public override bool Equals(object other) {"); + Indent(ind + IndentAmount, wr); wr.WriteLine("return other is @{0} && _D.Equals(((@{0})other)._D);", DtT); - Indent(ind); wr.WriteLine("}"); + Indent(ind, wr); wr.WriteLine("}"); - Indent(ind); + Indent(ind, wr); wr.WriteLine("public override int GetHashCode() { return _D.GetHashCode(); }"); if (dt is IndDatatypeDecl) { - Indent(ind); + Indent(ind, wr); wr.WriteLine("public override string ToString() { return _D.ToString(); }"); } // query properties foreach (var ctor in dt.Ctors) { // public bool is_Ctor0 { get { return _D is Dt_Ctor0; } } - Indent(ind); + Indent(ind, wr); wr.WriteLine("public bool is_{0} {{ get {{ return _D is {1}_{0}{2}; }} }}", ctor.CompileName, dt.CompileName, DtT_TypeArgs); } if (dt.HasFinitePossibleValues) { - Indent(ind); + Indent(ind, wr); wr.WriteLine("public static System.Collections.Generic.IEnumerable<@{0}> AllSingletonConstructors {{", DtT); - Indent(ind + IndentAmount); + Indent(ind + IndentAmount, wr); wr.WriteLine("get {"); foreach (var ctr in dt.Ctors) { if (ctr.Formals.Count == 0) { - Indent(ind + IndentAmount + IndentAmount); + Indent(ind + IndentAmount + IndentAmount, wr); wr.WriteLine("yield return new @{0}(new {2}_{1}());", DtT, ctr.CompileName, dt.CompileName); } } - Indent(ind + IndentAmount + IndentAmount); + Indent(ind + IndentAmount + IndentAmount, wr); wr.WriteLine("yield break;"); - Indent(ind + IndentAmount); + Indent(ind + IndentAmount, wr); wr.WriteLine("}"); - Indent(ind); + Indent(ind, wr); wr.WriteLine("}"); } @@ -658,17 +651,17 @@ namespace Microsoft.Dafny { foreach (var arg in ctor.Formals) { if (!arg.IsGhost && arg.HasName) { // public T0 @Dtor0 { get { return ((DT_Ctor)_D).@Dtor0; } } - Indent(ind); - wr.WriteLine("public {0} dtor_{1} {{ get {{ return (({2}_{3}{4})_D).@{1}; }} }}", TypeName(arg.Type), arg.CompileName, dt.CompileName, ctor.CompileName, DtT_TypeArgs); + Indent(ind, wr); + wr.WriteLine("public {0} dtor_{1} {{ get {{ return (({2}_{3}{4})_D).@{1}; }} }}", TypeName(arg.Type, wr), arg.CompileName, dt.CompileName, ctor.CompileName, DtT_TypeArgs); } } } - Indent(indent); + Indent(indent, wr); wr.WriteLine("}"); } - int WriteFormals(string sep, List/*!*/ formals) + int WriteFormals(string sep, List/*!*/ formals, TextWriter wr) { Contract.Requires(sep != null); Contract.Requires(cce.NonNullElements(formals)); @@ -676,7 +669,7 @@ namespace Microsoft.Dafny { foreach (Formal arg in formals) { if (!arg.IsGhost) { string name = FormalName(arg, i); - wr.Write("{0}{1}{2} @{3}", sep, arg.InParam ? "" : "out ", TypeName(arg.Type), name); + wr.Write("{0}{1}{2} @{3}", sep, arg.InParam ? "" : "out ", TypeName(arg.Type, wr), name); sep = ", "; i++; } @@ -732,13 +725,13 @@ namespace Microsoft.Dafny { return s; } - string DtCtorName(DatatypeCtor ctor, List typeArgs) { + string DtCtorName(DatatypeCtor ctor, List typeArgs, TextWriter wr) { Contract.Requires(ctor != null); Contract.Ensures(Contract.Result() != null); var s = DtCtorName(ctor); if (typeArgs != null && typeArgs.Count != 0) { - s += "<" + TypeNames(typeArgs) + ">"; + s += "<" + TypeNames(typeArgs, wr) + ">"; } return s; } @@ -776,7 +769,7 @@ namespace Microsoft.Dafny { } } - void CompileClassMembers(ClassDecl c, bool forCompanionClass, int indent) { + void CompileClassMembers(ClassDecl c, bool forCompanionClass, int indent, TextWriter wr) { Contract.Requires(c != null); Contract.Requires(!forCompanionClass || c is TraitDecl); Contract.Requires(0 <= indent); @@ -785,9 +778,9 @@ namespace Microsoft.Dafny { if (member is Field) { var f = (Field)member; // every field is inherited - Indent(indent); - wr.WriteLine("public {0} @_{1};", TypeName(f.Type), f.CompileName); - wr.Write("public {0} @{1}", TypeName(f.Type), f.CompileName); + Indent(indent, wr); + wr.WriteLine("public {0} @_{1};", TypeName(f.Type, wr), f.CompileName); + wr.Write("public {0} @{1}", TypeName(f.Type, wr), f.CompileName); wr.WriteLine(" {"); wr.WriteLine(" get { "); wr.Write("return this.@_{0};", f.CompileName); @@ -799,11 +792,11 @@ namespace Microsoft.Dafny { } else if (member is Function) { var f = (Function)member; Contract.Assert(f.Body != null); - CompileFunction(indent, f); + CompileFunction(indent, f, wr); } else if (member is Method) { var method = (Method)member; Contract.Assert(method.Body != null); - CompileMethod(c, indent, method); + CompileMethod(c, indent, method, wr); } else { Contract.Assert(false); // unexpected member } @@ -814,12 +807,12 @@ namespace Microsoft.Dafny { if (f.IsGhost || forCompanionClass) { // emit nothing } else if (c is TraitDecl) { - Indent(indent); - wr.Write("{0} @{1}", TypeName(f.Type), f.CompileName); + Indent(indent, wr); + wr.Write("{0} @{1}", TypeName(f.Type, wr), f.CompileName); wr.WriteLine(" { get; set; }"); } else { - Indent(indent); - wr.WriteLine("public {0} @{1} = {2};", TypeName(f.Type), f.CompileName, DefaultValue(f.Type)); + Indent(indent, wr); + wr.WriteLine("public {0} @{1} = {2};", TypeName(f.Type, wr), f.CompileName, DefaultValue(f.Type, wr)); } } else if (member is Function) { var f = (Function)member; @@ -828,29 +821,29 @@ namespace Microsoft.Dafny { if (forCompanionClass || Attributes.Contains(f.Attributes, "axiom")) { // suppress error message (in the case of "forCompanionClass", the non-forCompanionClass call will produce the error message) } else { - Error("Function {0} has no body", f.FullName); + Error("Function {0} has no body", wr, f.FullName); } } else if (f.IsGhost) { // nothing to compile, but we do check for assumes if (f.Body == null) { Contract.Assert(c is TraitDecl && !f.IsStatic); } else { - var v = new CheckHasNoAssumes_Visitor(this); + var v = new CheckHasNoAssumes_Visitor(this, wr); v.Visit(f.Body); } } else if (c is TraitDecl && !forCompanionClass) { // include it, unless it's static if (!f.IsStatic) { - Indent(indent); - wr.Write("{0} @{1}", TypeName(f.ResultType), f.CompileName); + Indent(indent, wr); + wr.Write("{0} @{1}", TypeName(f.ResultType, wr), f.CompileName); wr.Write("("); - WriteFormals("", f.Formals); + WriteFormals("", f.Formals, wr); wr.WriteLine(");"); } } else if (forCompanionClass && !f.IsStatic) { // companion classes only has static members } else { - CompileFunction(indent, f); + CompileFunction(indent, f, wr); } } else if (member is Method) { var m = (Method)member; @@ -859,30 +852,30 @@ namespace Microsoft.Dafny { if (forCompanionClass || Attributes.Contains(m.Attributes, "axiom")) { // suppress error message (in the case of "forCompanionClass", the non-forCompanionClass call will produce the error message) } else { - Error("Method {0} has no body", m.FullName); + Error("Method {0} has no body", wr, m.FullName); } } else if (m.IsGhost) { // nothing to compile, but we do check for assumes if (m.Body == null) { Contract.Assert(c is TraitDecl && !m.IsStatic); } else { - var v = new CheckHasNoAssumes_Visitor(this); + var v = new CheckHasNoAssumes_Visitor(this, wr); v.Visit(m.Body); } } else if (c is TraitDecl && !forCompanionClass) { // include it, unless it's static if (!m.IsStatic) { - Indent(indent); + Indent(indent, wr); wr.Write("void @{0}", m.CompileName); wr.Write("("); - int nIns = WriteFormals("", m.Ins); - WriteFormals(nIns == 0 ? "" : ", ", m.Outs); + int nIns = WriteFormals("", m.Ins, wr); + WriteFormals(nIns == 0 ? "" : ", ", m.Outs, wr); wr.WriteLine(");"); } } else if (forCompanionClass && !m.IsStatic) { // companion classes only has static members } else { - CompileMethod(c, indent, m); + CompileMethod(c, indent, m, wr); } } else { Contract.Assert(false); throw new cce.UnreachableException(); // unexpected member @@ -890,59 +883,59 @@ namespace Microsoft.Dafny { } } - private void CompileFunction(int indent, Function f) { - Indent(indent); - wr.Write("public {0}{1} @{2}", f.IsStatic ? "static " : "", TypeName(f.ResultType), f.CompileName); + private void CompileFunction(int indent, Function f, TextWriter wr) { + Indent(indent, wr); + wr.Write("public {0}{1} @{2}", f.IsStatic ? "static " : "", TypeName(f.ResultType, wr), f.CompileName); if (f.TypeArgs.Count != 0) { wr.Write("<{0}>", TypeParameters(f.TypeArgs)); } wr.Write("("); - WriteFormals("", f.Formals); + WriteFormals("", f.Formals, wr); wr.WriteLine(") {"); - CompileReturnBody(f.Body, indent + IndentAmount); - Indent(indent); wr.WriteLine("}"); + CompileReturnBody(f.Body, indent + IndentAmount, wr); + Indent(indent, wr); wr.WriteLine("}"); } - private void CompileMethod(ClassDecl c, int indent, Method m) { - Indent(indent); + private void CompileMethod(ClassDecl c, int indent, Method m, TextWriter wr) { + Indent(indent, wr); wr.Write("public {0}void @{1}", m.IsStatic ? "static " : "", m.CompileName); if (m.TypeArgs.Count != 0) { wr.Write("<{0}>", TypeParameters(m.TypeArgs)); } wr.Write("("); - int nIns = WriteFormals("", m.Ins); - WriteFormals(nIns == 0 ? "" : ", ", m.Outs); + int nIns = WriteFormals("", m.Ins, wr); + WriteFormals(nIns == 0 ? "" : ", ", m.Outs, wr); wr.WriteLine(")"); - Indent(indent); wr.WriteLine("{"); + Indent(indent, wr); wr.WriteLine("{"); foreach (Formal p in m.Outs) { if (!p.IsGhost) { - Indent(indent + IndentAmount); - wr.WriteLine("@{0} = {1};", p.CompileName, DefaultValue(p.Type)); + Indent(indent + IndentAmount, wr); + wr.WriteLine("@{0} = {1};", p.CompileName, DefaultValue(p.Type, wr)); } } if (m.Body == null) { - Error("Method {0} has no body", m.FullName); + Error("Method {0} has no body", wr, m.FullName); } else { if (m.IsTailRecursive) { - Indent(indent); wr.WriteLine("TAIL_CALL_START: ;"); + Indent(indent, wr); wr.WriteLine("TAIL_CALL_START: ;"); if (!m.IsStatic) { - Indent(indent + IndentAmount); wr.WriteLine("var _this = this;"); + Indent(indent + IndentAmount, wr); wr.WriteLine("var _this = this;"); } } Contract.Assert(enclosingMethod == null); enclosingMethod = m; - TrStmtList(m.Body.Body, indent); + TrStmtList(m.Body.Body, indent, wr); Contract.Assert(enclosingMethod == m); enclosingMethod = null; } - Indent(indent); wr.WriteLine("}"); + Indent(indent, wr); wr.WriteLine("}"); // allow the Main method to be an instance method if (!m.IsStatic && IsMain(m)) { - Indent(indent); + Indent(indent, wr); wr.WriteLine("public static void Main(string[] args) {"); Contract.Assert(m.EnclosingClass == c); - Indent(indent + IndentAmount); + Indent(indent + IndentAmount, wr); wr.Write("@{0} b = new @{0}", c.CompileName); if (c.TypeArgs.Count != 0) { // instantiate every parameter, it doesn't particularly matter how @@ -955,12 +948,12 @@ namespace Microsoft.Dafny { wr.Write(">"); } wr.WriteLine("();"); - Indent(indent + IndentAmount); wr.WriteLine("b.@Main();"); - Indent(indent); wr.WriteLine("}"); + Indent(indent + IndentAmount, wr); wr.WriteLine("b.@Main();"); + Indent(indent, wr); wr.WriteLine("}"); } } - void TrCasePatternOpt(CasePattern pat, Expression rhs, string rhs_string, int indent) { + void TrCasePatternOpt(CasePattern pat, Expression rhs, string rhs_string, int indent, TextWriter wr, bool inLetExprBody) { Contract.Requires(pat != null); Contract.Requires(pat.Var != null || rhs != null); if (pat.Var != null) { @@ -970,10 +963,10 @@ namespace Microsoft.Dafny { // var x := G; var bv = pat.Var; if (!bv.IsGhost) { - Indent(indent); - wr.Write("{0} {1} = ", TypeName(bv.Type), "@" + bv.CompileName); + Indent(indent, wr); + wr.Write("{0} {1} = ", TypeName(bv.Type, wr), "@" + bv.CompileName); if (rhs != null) { - TrExpr(rhs); + TrExpr(rhs, wr, inLetExprBody); } else { wr.Write(rhs_string); } @@ -992,9 +985,9 @@ namespace Microsoft.Dafny { // Create the temporary variable to hold G var tmp_name = idGenerator.FreshId("_let_tmp_rhs"); - Indent(indent); - wr.Write("{0} {1} = ", TypeName(rhs.Type), tmp_name); - TrExpr(rhs); + Indent(indent, wr); + wr.Write("{0} {1} = ", TypeName(rhs.Type, wr), tmp_name); + TrExpr(rhs, wr, inLetExprBody); wr.WriteLine(";"); var k = 0; // number of non-ghost formals processed @@ -1005,21 +998,21 @@ namespace Microsoft.Dafny { // nothing to compile, but do a sanity check Contract.Assert(!Contract.Exists(arg.Vars, bv => !bv.IsGhost)); } else { - TrCasePatternOpt(arg, null, string.Format("(({0})({1})._D).@{2}", DtCtorName(ctor, ((DatatypeValue)pat.Expr).InferredTypeArgs), tmp_name, FormalName(formal, k)), indent); + TrCasePatternOpt(arg, null, string.Format("(({0})({1})._D).@{2}", DtCtorName(ctor, ((DatatypeValue)pat.Expr).InferredTypeArgs, wr), tmp_name, FormalName(formal, k)), indent, wr, inLetExprBody); k++; } } } } - void ReturnExpr(Expression expr, int indent) { - Indent(indent); + void ReturnExpr(Expression expr, int indent, TextWriter wr, bool inLetExprBody) { + Indent(indent, wr); wr.Write("return "); - TrExpr(expr); + TrExpr(expr, wr, inLetExprBody); wr.WriteLine(";"); } - void TrExprOpt(Expression expr, int indent) { + void TrExprOpt(Expression expr, int indent, TextWriter wr, bool inLetExprBody) { Contract.Requires(expr != null); if (expr is LetExpr) { var e = (LetExpr)expr; @@ -1027,25 +1020,25 @@ namespace Microsoft.Dafny { for (int i = 0; i < e.LHSs.Count; i++) { var lhs = e.LHSs[i]; if (Contract.Exists(lhs.Vars, bv => !bv.IsGhost)) { - TrCasePatternOpt(lhs, e.RHSs[i], null, indent); + TrCasePatternOpt(lhs, e.RHSs[i], null, indent, wr, inLetExprBody); } } - TrExprOpt(e.Body, indent); + TrExprOpt(e.Body, indent, wr, inLetExprBody); } else { // We haven't optimized the other cases, so fallback to normal compilation - ReturnExpr(e, indent); + ReturnExpr(e, indent, wr, inLetExprBody); } } else if (expr is ITEExpr) { ITEExpr e = (ITEExpr)expr; - Indent(indent); + Indent(indent, wr); wr.Write("if ("); - TrExpr(e.Test); + TrExpr(e.Test, wr, inLetExprBody); wr.Write(") {\n"); - TrExprOpt(e.Thn, indent + IndentAmount); - Indent(indent); + TrExprOpt(e.Thn, indent + IndentAmount, wr, inLetExprBody); + Indent(indent, wr); wr.WriteLine("} else {"); - TrExprOpt(e.Els, indent + IndentAmount); - Indent(indent); + TrExprOpt(e.Els, indent + IndentAmount, wr, inLetExprBody); + Indent(indent, wr); wr.WriteLine("}"); } else if (expr is MatchExpr) { var e = (MatchExpr)expr; @@ -1060,9 +1053,9 @@ namespace Microsoft.Dafny { // ... // } string source = idGenerator.FreshId("_source"); - Indent(indent); - wr.Write("{0} {1} = ", TypeName(e.Source.Type), source); - TrExpr(e.Source); + Indent(indent, wr); + wr.Write("{0} {1} = ", TypeName(e.Source.Type, wr), source); + TrExpr(e.Source, wr, inLetExprBody); wr.WriteLine(";"); if (e.Cases.Count == 0) { @@ -1073,28 +1066,28 @@ namespace Microsoft.Dafny { var sourceType = (UserDefinedType)e.Source.Type.NormalizeExpand(); foreach (MatchCaseExpr mc in e.Cases) { //Indent(indent); - MatchCasePrelude(source, sourceType, cce.NonNull(mc.Ctor), mc.Arguments, i, e.Cases.Count, indent); - TrExprOpt(mc.Body, indent + IndentAmount); + MatchCasePrelude(source, sourceType, cce.NonNull(mc.Ctor), mc.Arguments, i, e.Cases.Count, indent, wr); + TrExprOpt(mc.Body, indent + IndentAmount, wr, inLetExprBody); i++; } - Indent(indent); + Indent(indent, wr); wr.WriteLine("}"); } } else if (expr is StmtExpr) { var e = (StmtExpr)expr; - TrExprOpt(e.E, indent); + TrExprOpt(e.E, indent, wr, inLetExprBody); } else { // We haven't optimized any other cases, so fallback to normal compilation - ReturnExpr(expr, indent); + ReturnExpr(expr, indent, wr, inLetExprBody); } } - void CompileReturnBody(Expression body, int indent) { + void CompileReturnBody(Expression body, int indent, TextWriter wr) { Contract.Requires(0 <= indent); body = body.Resolved; //Indent(indent); //wr.Write("return "); - TrExprOpt(body, indent); + TrExprOpt(body, indent, wr, false); //wr.WriteLine(";"); } @@ -1113,23 +1106,23 @@ namespace Microsoft.Dafny { return null; } - string TypeName_Companion(Type type) { + string TypeName_Companion(Type type, TextWriter wr) { Contract.Requires(type != null); var udt = type as UserDefinedType; if (udt != null && udt.ResolvedClass is TraitDecl) { string s = udt.FullCompanionCompileName; if (udt.TypeArgs.Count != 0) { if (udt.TypeArgs.Exists(argType => argType is ObjectType)) { - Error("compilation does not support type 'object' as a type parameter; consider introducing a ghost"); + Error("compilation does not support type 'object' as a type parameter; consider introducing a ghost", wr); } - s += "<" + TypeNames(udt.TypeArgs) + ">"; + s += "<" + TypeNames(udt.TypeArgs, wr) + ">"; } return s; } else { - return TypeName(type); + return TypeName(type, wr); } } - string TypeName(Type type) + string TypeName(Type type, TextWriter wr) { Contract.Requires(type != null); Contract.Ensures(Contract.Result() != null); @@ -1153,14 +1146,14 @@ namespace Microsoft.Dafny { if (nativeType != null) { return nativeType.Name; } - return TypeName(xType.AsNewtype.BaseType); + return TypeName(xType.AsNewtype.BaseType, wr); } else if (xType is ObjectType) { return "object"; } else if (xType.IsArrayType) { ArrayClassDecl at = xType.AsArrayType; Contract.Assert(at != null); // follows from type.IsArrayType Type elType = UserDefinedType.ArrayElementType(xType); - string name = TypeName(elType) + "["; + string name = TypeName(elType, wr) + "["; for (int i = 1; i < at.Dims; i++) { name += ","; } @@ -1184,54 +1177,60 @@ namespace Microsoft.Dafny { } s = rc.FullCompileName; } - return TypeName_UDT(s, udt.TypeArgs); + return TypeName_UDT(s, udt.TypeArgs, wr); } else if (xType is SetType) { Type argType = ((SetType)xType).Arg; if (argType is ObjectType) { - Error("compilation of set is not supported; consider introducing a ghost"); + Error("compilation of set is not supported; consider introducing a ghost", wr); } - return DafnySetClass + "<" + TypeName(argType) + ">"; + return DafnySetClass + "<" + TypeName(argType, wr) + ">"; } else if (xType is SeqType) { Type argType = ((SeqType)xType).Arg; if (argType is ObjectType) { - Error("compilation of seq is not supported; consider introducing a ghost"); + Error("compilation of seq is not supported; consider introducing a ghost", wr); } - return DafnySeqClass + "<" + TypeName(argType) + ">"; + return DafnySeqClass + "<" + TypeName(argType, wr) + ">"; } else if (xType is MultiSetType) { Type argType = ((MultiSetType)xType).Arg; if (argType is ObjectType) { - Error("compilation of seq is not supported; consider introducing a ghost"); + Error("compilation of seq is not supported; consider introducing a ghost", wr); } - return DafnyMultiSetClass + "<" + TypeName(argType) + ">"; + return DafnyMultiSetClass + "<" + TypeName(argType, wr) + ">"; } else if (xType is MapType) { Type domType = ((MapType)xType).Domain; Type ranType = ((MapType)xType).Range; if (domType is ObjectType || ranType is ObjectType) { - Error("compilation of map or map<_, object> is not supported; consider introducing a ghost"); + Error("compilation of map or map<_, object> is not supported; consider introducing a ghost", wr); } - return DafnyMapClass + "<" + TypeName(domType) + "," + TypeName(ranType) + ">"; + return DafnyMapClass + "<" + TypeName(domType, wr) + "," + TypeName(ranType, wr) + ">"; } else { Contract.Assert(false); throw new cce.UnreachableException(); // unexpected type } } - string TypeName_UDT(string fullCompileName, List typeArgs) { + string TypeName_UDT(string fullCompileName, List typeArgs, TextWriter wr) { Contract.Requires(fullCompileName != null); Contract.Requires(typeArgs != null); string s = "@" + fullCompileName; if (typeArgs.Count != 0) { if (typeArgs.Exists(argType => argType is ObjectType)) { - Error("compilation does not support type 'object' as a type parameter; consider introducing a ghost"); + Error("compilation does not support type 'object' as a type parameter; consider introducing a ghost", wr); } - s += "<" + TypeNames(typeArgs) + ">"; + s += "<" + TypeNames(typeArgs, wr) + ">"; } return s; } - string/*!*/ TypeNames(List/*!*/ types) { + string/*!*/ TypeNames(List/*!*/ types, TextWriter wr) { Contract.Requires(cce.NonNullElements(types)); Contract.Ensures(Contract.Result() != null); - return Util.Comma(types, TypeName); + string res = ""; + string c = ""; + foreach (var t in types) { + res += c + TypeName(t, wr); + c = ","; + } + return res; } string/*!*/ TypeParameters(List/*!*/ targs) { @@ -1241,7 +1240,7 @@ namespace Microsoft.Dafny { return Util.Comma(targs, tp => "@" + tp.CompileName); } - string DefaultValue(Type type) + string DefaultValue(Type type, TextWriter wr) { Contract.Requires(type != null); Contract.Ensures(Contract.Result() != null); @@ -1264,9 +1263,9 @@ namespace Microsoft.Dafny { if (xType.AsNewtype.NativeType != null) { return "0"; } - return DefaultValue(xType.AsNewtype.BaseType); + return DefaultValue(xType.AsNewtype.BaseType, wr); } else if (xType.IsRefType) { - return string.Format("({0})null", TypeName(xType)); + return string.Format("({0})null", TypeName(xType, wr)); } else if (xType.IsDatatype) { var udt = (UserDefinedType)xType; var s = "@" + udt.FullCompileName; @@ -1287,7 +1286,7 @@ namespace Microsoft.Dafny { s = "@" + rc.FullCompileName; } if (udt.TypeArgs.Count != 0) { - s += "<" + TypeNames(udt.TypeArgs) + ">"; + s += "<" + TypeNames(udt.TypeArgs, wr) + ">"; } return string.Format("new {0}()", s); } else if (xType.IsTypeParameter) { @@ -1295,18 +1294,18 @@ namespace Microsoft.Dafny { string s = "default(@" + udt.FullCompileName; if (udt.TypeArgs.Count != 0) { - s += "<" + TypeNames(udt.TypeArgs) + ">"; + s += "<" + TypeNames(udt.TypeArgs, wr) + ">"; } s += ")"; return s; } else if (xType is SetType) { - return DafnySetClass + "<" + TypeName(((SetType)xType).Arg) + ">.Empty"; + return DafnySetClass + "<" + TypeName(((SetType)xType).Arg, wr) + ">.Empty"; } else if (xType is MultiSetType) { - return DafnyMultiSetClass + "<" + TypeName(((MultiSetType)xType).Arg) + ">.Empty"; + return DafnyMultiSetClass + "<" + TypeName(((MultiSetType)xType).Arg, wr) + ">.Empty"; } else if (xType is SeqType) { - return DafnySeqClass + "<" + TypeName(((SeqType)xType).Arg) + ">.Empty"; + return DafnySeqClass + "<" + TypeName(((SeqType)xType).Arg, wr) + ">.Empty"; } else if (xType is MapType) { - return TypeName(xType)+".Empty"; + return TypeName(xType, wr) + ".Empty"; } else if (xType is ArrowType) { return "null"; } else { @@ -1319,59 +1318,61 @@ namespace Microsoft.Dafny { public class CheckHasNoAssumes_Visitor : BottomUpVisitor { readonly Compiler compiler; - public CheckHasNoAssumes_Visitor(Compiler c) { + TextWriter wr; + public CheckHasNoAssumes_Visitor(Compiler c, TextWriter wr) { Contract.Requires(c != null); compiler = c; + this.wr = wr; } protected override void VisitOneStmt(Statement stmt) { if (stmt is AssumeStmt) { - compiler.Error("an assume statement cannot be compiled (line {0})", stmt.Tok.line); + compiler.Error("an assume statement cannot be compiled (line {0})", wr, stmt.Tok.line); } else if (stmt is AssignSuchThatStmt) { var s = (AssignSuchThatStmt)stmt; if (s.AssumeToken != null) { - compiler.Error("an assume statement cannot be compiled (line {0})", s.AssumeToken.line); + compiler.Error("an assume statement cannot be compiled (line {0})", wr, s.AssumeToken.line); } } else if (stmt is ForallStmt) { var s = (ForallStmt)stmt; if (s.Body == null) { - compiler.Error("a forall statement without a body cannot be compiled (line {0})", stmt.Tok.line); + compiler.Error("a forall statement without a body cannot be compiled (line {0})", wr, stmt.Tok.line); } } else if (stmt is WhileStmt) { var s = (WhileStmt)stmt; if (s.Body == null) { - compiler.Error("a while statement without a body cannot be compiled (line {0})", stmt.Tok.line); + compiler.Error("a while statement without a body cannot be compiled (line {0})", wr, stmt.Tok.line); } } } } - void TrStmt(Statement stmt, int indent) + TextWriter TrStmt(Statement stmt, int indent) { Contract.Requires(stmt != null); + TextWriter wr = new StringWriter(); if (stmt.IsGhost) { - var v = new CheckHasNoAssumes_Visitor(this); + var v = new CheckHasNoAssumes_Visitor(this, wr); v.Visit(stmt); - Indent(indent); wr.WriteLine("{ }"); - return; + Indent(indent, wr); wr.WriteLine("{ }"); + return wr; } - if (stmt is PrintStmt) { PrintStmt s = (PrintStmt)stmt; foreach (var arg in s.Args) { - Indent(indent); + Indent(indent, wr); wr.Write("System.Console.Write("); - TrExpr(arg); + TrExpr(arg, wr, false); wr.WriteLine(");"); } } else if (stmt is BreakStmt) { var s = (BreakStmt)stmt; - Indent(indent); + Indent(indent, wr); wr.WriteLine("goto after_{0};", s.TargetStmt.Labels.Data.AssignUniqueId("after_", idGenerator)); } else if (stmt is ProduceStmt) { var s = (ProduceStmt)stmt; if (s.hiddenUpdate != null) - TrStmt(s.hiddenUpdate, indent); - Indent(indent); + wr.Write(TrStmt(s.hiddenUpdate, indent).ToString()); + Indent(indent, wr); if (s is YieldStmt) { wr.WriteLine("yield return null;"); } else { @@ -1381,7 +1382,7 @@ namespace Microsoft.Dafny { var s = (UpdateStmt)stmt; var resolved = s.ResolvedStatements; if (resolved.Count == 1) { - TrStmt(resolved[0], indent); + wr.Write(TrStmt(resolved[0], indent).ToString()); } else { // multi-assignment Contract.Assert(s.Lhss.Count == resolved.Count); @@ -1393,17 +1394,17 @@ namespace Microsoft.Dafny { var lhs = s.Lhss[i]; var rhs = s.Rhss[i]; if (!(rhs is HavocRhs)) { - lvalues.Add(CreateLvalue(lhs, indent)); + lvalues.Add(CreateLvalue(lhs, indent, wr)); string target = idGenerator.FreshId("_rhs"); rhss.Add(target); - TrRhs("var " + target, null, rhs, indent); + TrRhs("var " + target, null, rhs, indent, wr); } } } Contract.Assert(lvalues.Count == rhss.Count); for (int i = 0; i < lvalues.Count; i++) { - Indent(indent); + Indent(indent, wr); wr.WriteLine("{0} = {1};", lvalues[i], rhss[i]); } } @@ -1411,32 +1412,32 @@ namespace Microsoft.Dafny { } else if (stmt is AssignStmt) { AssignStmt s = (AssignStmt)stmt; Contract.Assert(!(s.Lhs is SeqSelectExpr) || ((SeqSelectExpr)s.Lhs).SelectOne); // multi-element array assignments are not allowed - TrRhs(null, s.Lhs, s.Rhs, indent); + TrRhs(null, s.Lhs, s.Rhs, indent, wr); } else if (stmt is AssignSuchThatStmt) { var s = (AssignSuchThatStmt)stmt; if (s.AssumeToken != null) { // Note, a non-ghost AssignSuchThatStmt may contain an assume - Error("an assume statement cannot be compiled (line {0})", s.AssumeToken.line); + Error("an assume statement cannot be compiled (line {0})", wr, s.AssumeToken.line); } else if (s.MissingBounds != null) { foreach (var bv in s.MissingBounds) { - Error("this assign-such-that statement is too advanced for the current compiler; Dafny's heuristics cannot find any bound for variable '{0}' (line {1})", bv.Name, s.Tok.line); + Error("this assign-such-that statement is too advanced for the current compiler; Dafny's heuristics cannot find any bound for variable '{0}' (line {1})", wr, bv.Name, s.Tok.line); } } else { Contract.Assert(s.Bounds != null); // follows from s.MissingBounds == null TrAssignSuchThat(indent, s.Lhss.ConvertAll(lhs => ((IdentifierExpr)lhs.Resolved).Var), // the resolver allows only IdentifierExpr left-hand sides - s.Expr, s.Bounds, s.Tok.line); + s.Expr, s.Bounds, s.Tok.line, wr, false); } } else if (stmt is CallStmt) { CallStmt s = (CallStmt)stmt; - TrCallStmt(s, null, indent); + wr.Write(TrCallStmt(s, null, indent).ToString()); } else if (stmt is BlockStmt) { - Indent(indent); wr.WriteLine("{"); - TrStmtList(((BlockStmt)stmt).Body, indent); - Indent(indent); wr.WriteLine("}"); + Indent(indent, wr); wr.WriteLine("{"); + TrStmtList(((BlockStmt)stmt).Body, indent, wr); + Indent(indent, wr); wr.WriteLine("}"); } else if (stmt is IfStmt) { IfStmt s = (IfStmt)stmt; @@ -1445,45 +1446,45 @@ namespace Microsoft.Dafny { if (s.Els == null) { // let's compile the "else" branch, since that involves no work // (still, let's leave a marker in the source code to indicate that this is what we did) - Indent(indent); + Indent(indent, wr); wr.WriteLine("if (!false) { }"); } else { // let's compile the "then" branch - Indent(indent); + Indent(indent, wr); wr.WriteLine("if (true)"); - TrStmt(s.Thn, indent); + wr.Write(TrStmt(s.Thn, indent).ToString()); } } else { - Indent(indent); wr.Write("if ("); - TrExpr(s.IsExistentialGuard ? Translator.AlphaRename((ExistsExpr)s.Guard, "eg_d", new Translator(null)) : s.Guard); + Indent(indent, wr); wr.Write("if ("); + TrExpr(s.IsExistentialGuard ? Translator.AlphaRename((ExistsExpr)s.Guard, "eg_d", new Translator(null)) : s.Guard, wr, false); wr.WriteLine(")"); // We'd like to do "TrStmt(s.Thn, indent)", except we want the scope of any existential variables to come inside the block - Indent(indent); wr.WriteLine("{"); + Indent(indent, wr); wr.WriteLine("{"); if (s.IsExistentialGuard) { - IntroduceAndAssignBoundVars(indent + IndentAmount, (ExistsExpr)s.Guard); + IntroduceAndAssignBoundVars(indent + IndentAmount, (ExistsExpr)s.Guard, wr); } - TrStmtList(s.Thn.Body, indent); - Indent(indent); wr.WriteLine("}"); + TrStmtList(s.Thn.Body, indent, wr); + Indent(indent, wr); wr.WriteLine("}"); if (s.Els != null) { - Indent(indent); wr.WriteLine("else"); - TrStmt(s.Els, indent); + Indent(indent, wr); wr.WriteLine("else"); + wr.Write(TrStmt(s.Els, indent).ToString()); } } } else if (stmt is AlternativeStmt) { var s = (AlternativeStmt)stmt; - Indent(indent); + Indent(indent, wr); foreach (var alternative in s.Alternatives) { wr.Write("if ("); - TrExpr(alternative.IsExistentialGuard ? Translator.AlphaRename((ExistsExpr)alternative.Guard, "eg_d", new Translator(null)) : alternative.Guard); + TrExpr(alternative.IsExistentialGuard ? Translator.AlphaRename((ExistsExpr)alternative.Guard, "eg_d", new Translator(null)) : alternative.Guard, wr, false); wr.WriteLine(") {"); if (alternative.IsExistentialGuard) { - IntroduceAndAssignBoundVars(indent + IndentAmount, (ExistsExpr)alternative.Guard); + IntroduceAndAssignBoundVars(indent + IndentAmount, (ExistsExpr)alternative.Guard, wr); } - TrStmtList(alternative.Body, indent); - Indent(indent); + TrStmtList(alternative.Body, indent, wr); + Indent(indent, wr); wr.Write("} else "); } wr.WriteLine("{ /*unreachable alternative*/ }"); @@ -1491,38 +1492,38 @@ namespace Microsoft.Dafny { } else if (stmt is WhileStmt) { WhileStmt s = (WhileStmt)stmt; if (s.Body == null) { - return; + return wr; } if (s.Guard == null) { - Indent(indent); + Indent(indent, wr); wr.WriteLine("while (false) { }"); } else { - Indent(indent); + Indent(indent, wr); wr.Write("while ("); - TrExpr(s.Guard); + TrExpr(s.Guard, wr, false); wr.WriteLine(")"); - TrStmt(s.Body, indent); + wr.Write(TrStmt(s.Body, indent).ToString()); } } else if (stmt is AlternativeLoopStmt) { var s = (AlternativeLoopStmt)stmt; if (s.Alternatives.Count != 0) { - Indent(indent); + Indent(indent, wr); wr.WriteLine("while (true) {"); int ind = indent + IndentAmount; foreach (var alternative in s.Alternatives) { } - Indent(ind); + Indent(ind, wr); foreach (var alternative in s.Alternatives) { wr.Write("if ("); - TrExpr(alternative.Guard); + TrExpr(alternative.Guard, wr, false); wr.WriteLine(") {"); - TrStmtList(alternative.Body, ind); - Indent(ind); + TrStmtList(alternative.Body, ind, wr); + Indent(ind, wr); wr.Write("} else "); } wr.WriteLine("{ break; }"); - Indent(indent); + Indent(indent, wr); wr.WriteLine("}"); } @@ -1530,17 +1531,17 @@ namespace Microsoft.Dafny { var s = (ForallStmt)stmt; if (s.Kind != ForallStmt.ParBodyKind.Assign) { // Call and Proof have no side effects, so they can simply be optimized away. - return; + return wr; } else if (s.BoundVars.Count == 0) { // the bound variables just spell out a single point, so the forall statement is equivalent to one execution of the body - TrStmt(s.Body, indent); - return; + wr.Write(TrStmt(s.Body, indent).ToString()); + return wr; } var s0 = (AssignStmt)s.S0; if (s0.Rhs is HavocRhs) { // The forall statement says to havoc a bunch of things. This can be efficiently compiled // into doing nothing. - return; + return wr; } var rhs = ((ExprRhs)s0.Rhs).Expr; @@ -1584,29 +1585,29 @@ namespace Microsoft.Dafny { if (s0.Lhs is MemberSelectExpr) { var lhs = (MemberSelectExpr)s0.Lhs; L = 2; - tupleTypeArgs = TypeName(lhs.Obj.Type); + tupleTypeArgs = TypeName(lhs.Obj.Type, wr); } else if (s0.Lhs is SeqSelectExpr) { var lhs = (SeqSelectExpr)s0.Lhs; L = 3; // note, we might as well do the BigInteger-to-int cast for array indices here, before putting things into the Tuple rather than when they are extracted from the Tuple - tupleTypeArgs = TypeName(lhs.Seq.Type) + ",int"; + tupleTypeArgs = TypeName(lhs.Seq.Type, wr) + ",int"; } else { var lhs = (MultiSelectExpr)s0.Lhs; L = 2 + lhs.Indices.Count; if (8 < L) { - Error("compiler currently does not support assignments to more-than-6-dimensional arrays in forall statements"); - return; + Error("compiler currently does not support assignments to more-than-6-dimensional arrays in forall statements", wr); + return wr; } - tupleTypeArgs = TypeName(lhs.Array.Type); + tupleTypeArgs = TypeName(lhs.Array.Type, wr); for (int i = 0; i < lhs.Indices.Count; i++) { // note, we might as well do the BigInteger-to-int cast for array indices here, before putting things into the Tuple rather than when they are extracted from the Tuple tupleTypeArgs += ",int"; } } - tupleTypeArgs += "," + TypeName(rhs.Type); + tupleTypeArgs += "," + TypeName(rhs.Type, wr); // declare and construct "ingredients" - Indent(indent); + Indent(indent, wr); wr.WriteLine("var {0} = new System.Collections.Generic.List>();", ingredients, tupleTypeArgs); var n = s.BoundVars.Count; @@ -1616,38 +1617,38 @@ namespace Microsoft.Dafny { var bound = s.Bounds[i]; var bv = s.BoundVars[i]; if (bound is ComprehensionExpr.BoolBoundedPool) { - Indent(ind); + Indent(ind, wr); wr.Write("foreach (var @{0} in Dafny.Helpers.AllBooleans) {{ ", bv.CompileName); } else if (bound is ComprehensionExpr.CharBoundedPool) { - Indent(ind); + Indent(ind, wr); wr.Write("foreach (var @{0} in Dafny.Helpers.AllChars) {{ ", bv.CompileName); } else if (bound is ComprehensionExpr.IntBoundedPool) { var b = (ComprehensionExpr.IntBoundedPool)bound; - Indent(ind); + Indent(ind, wr); if (AsNativeType(bv.Type) != null) { wr.Write("foreach (var @{0} in @{1}.IntegerRange(", bv.CompileName, bv.Type.AsNewtype.FullCompileName); } else { wr.Write("foreach (var @{0} in Dafny.Helpers.IntegerRange(", bv.CompileName); } - TrExpr(b.LowerBound); + TrExpr(b.LowerBound, wr, false); wr.Write(", "); - TrExpr(b.UpperBound); + TrExpr(b.UpperBound, wr, false); wr.Write(")) { "); } else if (bound is ComprehensionExpr.SetBoundedPool) { var b = (ComprehensionExpr.SetBoundedPool)bound; - Indent(ind); + Indent(ind, wr); wr.Write("foreach (var @{0} in (", bv.CompileName); - TrExpr(b.Set); + TrExpr(b.Set, wr, false); wr.Write(").Elements) { "); } else if (bound is ComprehensionExpr.SeqBoundedPool) { var b = (ComprehensionExpr.SeqBoundedPool)bound; - Indent(ind); + Indent(ind, wr); wr.Write("foreach (var @{0} in (", bv.CompileName); - TrExpr(b.Seq); + TrExpr(b.Seq, wr, false); wr.Write(").UniqueElements) { "); } else if (bound is ComprehensionExpr.DatatypeBoundedPool) { var b = (ComprehensionExpr.DatatypeBoundedPool)bound; - wr.Write("foreach (var @{0} in {1}.AllSingletonConstructors) {{", bv.CompileName, TypeName(bv.Type)); + wr.Write("foreach (var @{0} in {1}.AllSingletonConstructors) {{", bv.CompileName, TypeName(bv.Type, wr)); } else { Contract.Assert(false); throw new cce.UnreachableException(); // unexpected BoundedPool type } @@ -1657,55 +1658,55 @@ namespace Microsoft.Dafny { // if (range) { // ingredients.Add(new L-Tuple( LHS0(w,x,y,z), LHS1(w,x,y,z), ..., RHS(w,x,y,z) )); // } - Indent(indent + n * IndentAmount); + Indent(indent + n * IndentAmount, wr); wr.Write("if ("); foreach (var bv in s.BoundVars) { if (bv.Type.NormalizeExpand() is NatType) { wr.Write("0 <= {0} && ", bv.CompileName); } } - TrExpr(s.Range); + TrExpr(s.Range, wr, false); wr.WriteLine(") {"); var indFinal = indent + (n + 1) * IndentAmount; - Indent(indFinal); + Indent(indFinal, wr); wr.Write("{0}.Add(new System.Tuple<{1}>(", ingredients, tupleTypeArgs); if (s0.Lhs is MemberSelectExpr) { var lhs = (MemberSelectExpr)s0.Lhs; - TrExpr(lhs.Obj); + TrExpr(lhs.Obj, wr, false); } else if (s0.Lhs is SeqSelectExpr) { var lhs = (SeqSelectExpr)s0.Lhs; - TrExpr(lhs.Seq); + TrExpr(lhs.Seq, wr, false); wr.Write(", (int)("); - TrExpr(lhs.E0); + TrExpr(lhs.E0, wr, false); wr.Write(")"); } else { var lhs = (MultiSelectExpr)s0.Lhs; - TrExpr(lhs.Array); + TrExpr(lhs.Array, wr, false); for (int i = 0; i < lhs.Indices.Count; i++) { wr.Write(", (int)("); - TrExpr(lhs.Indices[i]); + TrExpr(lhs.Indices[i], wr, false); wr.Write(")"); } } wr.Write(", "); - TrExpr(rhs); + TrExpr(rhs, wr, false); wr.WriteLine("));"); - Indent(indent + n * IndentAmount); + Indent(indent + n * IndentAmount, wr); wr.WriteLine("}"); for (int i = n; 0 <= --i; ) { - Indent(indent + i * IndentAmount); + Indent(indent + i * IndentAmount, wr); wr.WriteLine("}"); } // foreach (L-Tuple l in ingredients) { // LHS[ l0, l1, l2, ..., l(L-2) ] = l(L-1); // } - Indent(indent); + Indent(indent, wr); wr.WriteLine("foreach (var {0} in {1}) {{", tup, ingredients); - Indent(indent + IndentAmount); + Indent(indent + IndentAmount, wr); if (s0.Lhs is MemberSelectExpr) { var lhs = (MemberSelectExpr)s0.Lhs; wr.WriteLine("{0}.Item1.@{1} = {0}.Item2;", tup, lhs.MemberName); @@ -1722,7 +1723,7 @@ namespace Microsoft.Dafny { } wr.WriteLine("] = {0}.Item{1};", tup, L); } - Indent(indent); + Indent(indent, wr); wr.WriteLine("}"); } else if (stmt is MatchStmt) { @@ -1739,54 +1740,56 @@ namespace Microsoft.Dafny { // } if (s.Cases.Count != 0) { string source = idGenerator.FreshId("_source"); - Indent(indent); - wr.Write("{0} {1} = ", TypeName(cce.NonNull(s.Source.Type)), source); - TrExpr(s.Source); + Indent(indent, wr); + wr.Write("{0} {1} = ", TypeName(cce.NonNull(s.Source.Type), wr), source); + TrExpr(s.Source, wr, false); wr.WriteLine(";"); int i = 0; var sourceType = (UserDefinedType)s.Source.Type.NormalizeExpand(); foreach (MatchCaseStmt mc in s.Cases) { - MatchCasePrelude(source, sourceType, cce.NonNull(mc.Ctor), mc.Arguments, i, s.Cases.Count, indent); - TrStmtList(mc.Body, indent); + MatchCasePrelude(source, sourceType, cce.NonNull(mc.Ctor), mc.Arguments, i, s.Cases.Count, indent, wr); + TrStmtList(mc.Body, indent, wr); i++; } - Indent(indent); wr.WriteLine("}"); + Indent(indent, wr); wr.WriteLine("}"); } } else if (stmt is VarDeclStmt) { var s = (VarDeclStmt)stmt; foreach (var local in s.Locals) { - TrLocalVar(local, true, indent); + TrLocalVar(local, true, indent, wr); } if (s.Update != null) { - TrStmt(s.Update, indent); + wr.Write(TrStmt(s.Update, indent).ToString()); } } else if (stmt is ModifyStmt) { var s = (ModifyStmt)stmt; if (s.Body != null) { - TrStmt(s.Body, indent); + wr.Write(TrStmt(s.Body, indent).ToString()); } } else { Contract.Assert(false); throw new cce.UnreachableException(); // unexpected statement } + + return wr; } - private void IntroduceAndAssignBoundVars(int indent, ExistsExpr exists) { + private void IntroduceAndAssignBoundVars(int indent, ExistsExpr exists, TextWriter wr) { Contract.Requires(0 <= indent); Contract.Requires(exists != null); Contract.Assume(exists.Bounds != null); // follows from successful resolution Contract.Assert(exists.Range == null); // follows from invariant of class IfStmt foreach (var bv in exists.BoundVars) { - TrLocalVar(bv, false, indent); + TrLocalVar(bv, false, indent, wr); } var ivars = exists.BoundVars.ConvertAll(bv => (IVariable)bv); - TrAssignSuchThat(indent, ivars, exists.Term, exists.Bounds, exists.tok.line); + TrAssignSuchThat(indent, ivars, exists.Term, exists.Bounds, exists.tok.line, wr, false); } - private void TrAssignSuchThat(int indent, List lhss, Expression constraint, List bounds, int debuginfoLine) { + private void TrAssignSuchThat(int indent, List lhss, Expression constraint, List bounds, int debuginfoLine, TextWriter wr, bool inLetExprBody) { Contract.Requires(0 <= indent); Contract.Requires(lhss != null); Contract.Requires(constraint != null); @@ -1828,7 +1831,7 @@ namespace Microsoft.Dafny { int ind = indent; bool needIterLimit = lhss.Count != 1 && bounds.Exists(bnd => !bnd.IsFinite); if (needIterLimit) { - Indent(indent); + Indent(indent, wr); wr.WriteLine("for (var {0} = new BigInteger(5); ; {0} *= 2) {{", iterLimit); ind += IndentAmount; } @@ -1837,11 +1840,11 @@ namespace Microsoft.Dafny { var bound = bounds[i]; var bv = lhss[i]; if (needIterLimit) { - Indent(ind); + Indent(ind, wr); wr.WriteLine("var {0}_{1} = {0};", iterLimit, i); } var tmpVar = idGenerator.FreshId("_assign_such_that_"); - Indent(ind); + Indent(ind, wr); if (bound is ComprehensionExpr.BoolBoundedPool) { wr.WriteLine("foreach (var {0} in Dafny.Helpers.AllBooleans) {{ @{1} = {0};", tmpVar, bv.CompileName); } else if (bound is ComprehensionExpr.CharBoundedPool) { @@ -1856,13 +1859,13 @@ namespace Microsoft.Dafny { if (b.LowerBound == null) { wr.Write("null"); } else { - TrExpr(b.LowerBound); + TrExpr(b.LowerBound, wr, inLetExprBody); } wr.Write(", "); if (b.UpperBound == null) { wr.Write("null"); } else { - TrExpr(b.UpperBound); + TrExpr(b.UpperBound, wr, inLetExprBody); } wr.WriteLine(")) {{ @{1} = {0};", tmpVar, bv.CompileName); } else if (bound is AssignSuchThatStmt.WiggleWaggleBound) { @@ -1870,54 +1873,54 @@ namespace Microsoft.Dafny { } else if (bound is ComprehensionExpr.SetBoundedPool) { var b = (ComprehensionExpr.SetBoundedPool)bound; wr.Write("foreach (var {0} in (", tmpVar); - TrExpr(b.Set); + TrExpr(b.Set, wr, inLetExprBody); wr.WriteLine(").Elements) {{ @{0} = {1};", bv.CompileName, tmpVar); } else if (bound is ComprehensionExpr.SubSetBoundedPool) { var b = (ComprehensionExpr.SubSetBoundedPool)bound; wr.Write("foreach (var {0} in (", tmpVar); - TrExpr(b.UpperBound); + TrExpr(b.UpperBound, wr, inLetExprBody); wr.WriteLine(").AllSubsets) {{ @{0} = {1};", bv.CompileName, tmpVar); } else if (bound is ComprehensionExpr.MapBoundedPool) { var b = (ComprehensionExpr.MapBoundedPool)bound; wr.Write("foreach (var {0} in (", tmpVar); - TrExpr(b.Map); + TrExpr(b.Map, wr, inLetExprBody); wr.WriteLine(").Domain) {{ @{0} = {1};", bv.CompileName, tmpVar); } else if (bound is ComprehensionExpr.SeqBoundedPool) { var b = (ComprehensionExpr.SeqBoundedPool)bound; wr.Write("foreach (var {0} in (", tmpVar); - TrExpr(b.Seq); + TrExpr(b.Seq, wr, inLetExprBody); wr.WriteLine(").Elements) {{ @{0} = {1};", bv.CompileName, tmpVar); } else if (bound is ComprehensionExpr.DatatypeBoundedPool) { var b = (ComprehensionExpr.DatatypeBoundedPool)bound; - wr.WriteLine("foreach (var {0} in {1}.AllSingletonConstructors) {{ @{2} = {0};", tmpVar, TypeName(bv.Type), bv.CompileName); + wr.WriteLine("foreach (var {0} in {1}.AllSingletonConstructors) {{ @{2} = {0};", tmpVar, TypeName(bv.Type, wr), bv.CompileName); } else { Contract.Assert(false); throw new cce.UnreachableException(); // unexpected BoundedPool type } if (needIterLimit) { - Indent(ind + IndentAmount); + Indent(ind + IndentAmount, wr); wr.WriteLine("if ({0}_{1} == 0) {{ break; }} {0}_{1}--;", iterLimit, i); } } - Indent(ind); + Indent(ind, wr); wr.Write("if ("); - TrExpr(constraint); + TrExpr(constraint, wr, inLetExprBody); wr.WriteLine(") {"); - Indent(ind + IndentAmount); + Indent(ind + IndentAmount, wr); wr.WriteLine("goto {0};", doneLabel); - Indent(ind); + Indent(ind, wr); wr.WriteLine("}"); - Indent(indent); + Indent(indent, wr); for (int i = 0; i < n; i++) { wr.Write(i == 0 ? "}" : " }"); } wr.WriteLine(needIterLimit ? " }" : ""); - Indent(indent); + Indent(indent, wr); wr.WriteLine("throw new System.Exception(\"assign-such-that search produced no value (line {0})\");", debuginfoLine); - Indent(indent); + Indent(indent, wr); wr.WriteLine("{0}: ;", doneLabel); } - string CreateLvalue(Expression lhs, int indent) { + string CreateLvalue(Expression lhs, int indent, TextWriter wr) { lhs = lhs.Resolved; if (lhs is IdentifierExpr) { var ll = (IdentifierExpr)lhs; @@ -1925,9 +1928,9 @@ namespace Microsoft.Dafny { } else if (lhs is MemberSelectExpr) { var ll = (MemberSelectExpr)lhs; string obj = idGenerator.FreshId("_obj"); - Indent(indent); + Indent(indent, wr); wr.Write("var {0} = ", obj); - TrExpr(ll.Obj); + TrExpr(ll.Obj, wr, false); wr.WriteLine(";"); return string.Format("{0}.@{1}", obj, ll.Member.CompileName); } else if (lhs is SeqSelectExpr) { @@ -1935,31 +1938,31 @@ namespace Microsoft.Dafny { var c = idGenerator.FreshNumericId("_arr+_index"); string arr = "_arr" + c; string index = "_index" + c; - Indent(indent); + Indent(indent, wr); wr.Write("var {0} = ", arr); - TrExpr(ll.Seq); + TrExpr(ll.Seq, wr, false); wr.WriteLine(";"); - Indent(indent); + Indent(indent, wr); wr.Write("var {0} = ", index); - TrExpr(ll.E0); + TrExpr(ll.E0, wr, false); wr.WriteLine(";"); return string.Format("{0}[(int){1}]", arr, index); } else { var ll = (MultiSelectExpr)lhs; var c = idGenerator.FreshNumericId("_arr+_index"); string arr = "_arr" + c; - Indent(indent); + Indent(indent, wr); wr.Write("var {0} = ", arr); - TrExpr(ll.Array); + TrExpr(ll.Array, wr, false); wr.WriteLine(";"); string fullString = arr + "["; string sep = ""; int i = 0; foreach (var idx in ll.Indices) { string index = "_index" + i + "_" + c; - Indent(indent); + Indent(indent, wr); wr.Write("var {0} = ", index); - TrExpr(idx); + TrExpr(idx, wr, false); wr.WriteLine(";"); fullString += sep + "(int)" + index; sep = ", "; @@ -1969,21 +1972,21 @@ namespace Microsoft.Dafny { } } - void TrRhs(string target, Expression targetExpr, AssignmentRhs rhs, int indent) { + void TrRhs(string target, Expression targetExpr, AssignmentRhs rhs, int indent, TextWriter wr) { Contract.Requires((target == null) != (targetExpr == null)); var tRhs = rhs as TypeRhs; if (tRhs != null && tRhs.InitCall != null) { string nw = idGenerator.FreshId("_nw"); - Indent(indent); + Indent(indent, wr); wr.Write("var {0} = ", nw); - TrAssignmentRhs(rhs); // in this case, this call will not require us to spill any let variables first + TrAssignmentRhs(rhs, wr); // in this case, this call will not require us to spill any let variables first wr.WriteLine(";"); - TrCallStmt(tRhs.InitCall, nw, indent); - Indent(indent); + wr.Write(TrCallStmt(tRhs.InitCall, nw, indent).ToString()); + Indent(indent, wr); if (target != null) { wr.Write(target); } else { - TrExpr(targetExpr); + TrExpr(targetExpr, wr, false); } wr.WriteLine(" = {0};", nw); } else if (rhs is HavocRhs) { @@ -1994,22 +1997,23 @@ namespace Microsoft.Dafny { foreach (Expression dim in tRhs.ArrayDimensions) { } } - Indent(indent); + Indent(indent, wr); if (target != null) { wr.Write(target); } else { - TrExpr(targetExpr); + TrExpr(targetExpr, wr, false); } wr.Write(" = "); - TrAssignmentRhs(rhs); + TrAssignmentRhs(rhs, wr); wr.WriteLine(";"); } } - void TrCallStmt(CallStmt s, string receiverReplacement, int indent) { + TextWriter TrCallStmt(CallStmt s, string receiverReplacement, int indent) { Contract.Requires(s != null); Contract.Assert(s.Method != null); // follows from the fact that stmt has been successfully resolved + StringWriter wr = new StringWriter(); if (s.Method == enclosingMethod && enclosingMethod.IsTailRecursive) { // compile call as tail-recursive @@ -2026,9 +2030,9 @@ namespace Microsoft.Dafny { string inTmp = idGenerator.FreshId("_in"); inTmps.Add(inTmp); - Indent(indent); + Indent(indent, wr); wr.Write("var {0} = ", inTmp); - TrExpr(s.Receiver); + TrExpr(s.Receiver, wr, false); wr.WriteLine(";"); } for (int i = 0; i < s.Method.Ins.Count; i++) { @@ -2036,29 +2040,29 @@ namespace Microsoft.Dafny { if (!p.IsGhost) { string inTmp = idGenerator.FreshId("_in"); inTmps.Add(inTmp); - Indent(indent); + Indent(indent, wr); wr.Write("var {0} = ", inTmp); - TrExpr(s.Args[i]); + TrExpr(s.Args[i], wr, false); wr.WriteLine(";"); } } // Now, assign to the formals int n = 0; if (!s.Method.IsStatic) { - Indent(indent); + Indent(indent, wr); wr.WriteLine("_this = {0};", inTmps[n]); n++; } foreach (var p in s.Method.Ins) { if (!p.IsGhost) { - Indent(indent); + Indent(indent, wr); wr.WriteLine("{0} = {1};", p.CompileName, inTmps[n]); n++; } } Contract.Assert(n == inTmps.Count); // finally, the jump back to the head of the method - Indent(indent); + Indent(indent, wr); wr.WriteLine("goto TAIL_CALL_START;"); } else { @@ -2069,7 +2073,7 @@ namespace Microsoft.Dafny { for (int i = 0; i < s.Method.Outs.Count; i++) { Formal p = s.Method.Outs[i]; if (!p.IsGhost) { - lvalues.Add(CreateLvalue(s.Lhs[i], indent)); + lvalues.Add(CreateLvalue(s.Lhs[i], indent, wr)); } } var outTmps = new List(); @@ -2078,8 +2082,8 @@ namespace Microsoft.Dafny { if (!p.IsGhost) { string target = idGenerator.FreshId("_out"); outTmps.Add(target); - Indent(indent); - wr.WriteLine("{0} {1};", TypeName(s.Lhs[i].Type), target); + Indent(indent, wr); + wr.WriteLine("{0} {1};", TypeName(s.Lhs[i].Type, wr), target); } } Contract.Assert(lvalues.Count == outTmps.Count); @@ -2090,14 +2094,14 @@ namespace Microsoft.Dafny { } } if (receiverReplacement != null) { - Indent(indent); + Indent(indent, wr); wr.Write("@" + receiverReplacement); } else if (s.Method.IsStatic) { - Indent(indent); - wr.Write(TypeName_Companion(s.Receiver.Type)); + Indent(indent, wr); + wr.Write(TypeName_Companion(s.Receiver.Type, wr)); } else { - Indent(indent); - TrParenExpr(s.Receiver); + Indent(indent, wr); + TrParenExpr(s.Receiver, wr, false); } wr.Write(".@{0}(", s.Method.CompileName); @@ -2106,7 +2110,7 @@ namespace Microsoft.Dafny { Formal p = s.Method.Ins[i]; if (!p.IsGhost) { wr.Write(sep); - TrExpr(s.Args[i]); + TrExpr(s.Args[i], wr, false); sep = ", "; } } @@ -2119,44 +2123,45 @@ namespace Microsoft.Dafny { // assign to the actual LHSs for (int j = 0; j < lvalues.Count; j++) { - Indent(indent); + Indent(indent, wr); wr.WriteLine("{0} = {1};", lvalues[j], outTmps[j]); } } + return wr; } /// /// Before calling TrAssignmentRhs(rhs), the caller must have spilled the let variables declared in "rhs". /// - void TrAssignmentRhs(AssignmentRhs rhs) { + void TrAssignmentRhs(AssignmentRhs rhs, TextWriter wr) { Contract.Requires(rhs != null); Contract.Requires(!(rhs is HavocRhs)); if (rhs is ExprRhs) { ExprRhs e = (ExprRhs)rhs; - TrExpr(e.Expr); + TrExpr(e.Expr, wr, false); } else { TypeRhs tp = (TypeRhs)rhs; if (tp.ArrayDimensions == null) { - wr.Write("new {0}()", TypeName(tp.EType)); + wr.Write("new {0}()", TypeName(tp.EType, wr)); } else { if (tp.EType.IsIntegerType || tp.EType.IsTypeParameter) { // Because the default constructor for BigInteger does not generate a valid BigInteger, we have // to excplicitly initialize the elements of an integer array. This is all done in a helper routine. - wr.Write("Dafny.Helpers.InitNewArray{0}<{1}>", tp.ArrayDimensions.Count, TypeName(tp.EType)); + wr.Write("Dafny.Helpers.InitNewArray{0}<{1}>", tp.ArrayDimensions.Count, TypeName(tp.EType, wr)); string prefix = "("; foreach (Expression dim in tp.ArrayDimensions) { wr.Write(prefix); - TrParenExpr(dim); + TrParenExpr(dim, wr, false); prefix = ", "; } wr.Write(")"); } else { - wr.Write("new {0}", TypeName(tp.EType)); + wr.Write("new {0}", TypeName(tp.EType, wr)); string prefix = "["; foreach (Expression dim in tp.ArrayDimensions) { wr.Write("{0}(int)", prefix); - TrParenExpr(dim); + TrParenExpr(dim, wr, false); prefix = ", "; } wr.Write("]"); @@ -2165,34 +2170,43 @@ namespace Microsoft.Dafny { } } - void TrStmtList(List/*!*/ stmts, int indent) {Contract.Requires(cce.NonNullElements(stmts)); + void TrStmtList(List/*!*/ stmts, int indent, TextWriter writer) {Contract.Requires(cce.NonNullElements(stmts)); foreach (Statement ss in stmts) { - TrStmt(ss, indent + IndentAmount); + copyInstrWriter.Clear(); + TextWriter wr = TrStmt(ss, indent + IndentAmount); + // write out any copy instructions that copies the out param + // used in letexpr to a local + string copyInstr = copyInstrWriter.ToString(); + if (copyInstr != "") { + Indent(indent + IndentAmount, writer); + writer.Write(copyInstrWriter.ToString()); + } + writer.Write(wr.ToString()); if (ss.Labels != null) { - Indent(indent); // labels are not indented as much as the statements - wr.WriteLine("after_{0}: ;", ss.Labels.Data.AssignUniqueId("after_", idGenerator)); + Indent(indent, writer); // labels are not indented as much as the statements + writer.WriteLine("after_{0}: ;", ss.Labels.Data.AssignUniqueId("after_", idGenerator)); } } } - void TrLocalVar(IVariable v, bool alwaysInitialize, int indent) { + void TrLocalVar(IVariable v, bool alwaysInitialize, int indent, TextWriter wr) { Contract.Requires(v != null); if (v.IsGhost) { // only emit non-ghosts (we get here only for local variables introduced implicitly by call statements) return; } - Indent(indent); - wr.Write("{0} @{1}", TypeName(v.Type), v.CompileName); + Indent(indent, wr); + wr.Write("{0} @{1}", TypeName(v.Type, wr), v.CompileName); if (alwaysInitialize) { // produce a default value - wr.WriteLine(" = {0};", DefaultValue(v.Type)); + wr.WriteLine(" = {0};", DefaultValue(v.Type, wr)); } else { wr.WriteLine(";"); } } - void MatchCasePrelude(string source, UserDefinedType sourceType, DatatypeCtor ctor, List/*!*/ arguments, int caseIndex, int caseCount, int indent) { + void MatchCasePrelude(string source, UserDefinedType sourceType, DatatypeCtor ctor, List/*!*/ arguments, int caseIndex, int caseCount, int indent, TextWriter wr) { Contract.Requires(source != null); Contract.Requires(sourceType != null); Contract.Requires(ctor != null); @@ -2201,7 +2215,7 @@ namespace Microsoft.Dafny { // if (source.is_Ctor0) { // FormalType f0 = ((Dt_Ctor0)source._D).a0; // ... - Indent(indent); + Indent(indent, wr); wr.Write("{0}if (", caseIndex == 0 ? "" : "} else "); if (caseIndex == caseCount - 1) { wr.Write("true"); @@ -2216,9 +2230,9 @@ namespace Microsoft.Dafny { if (!arg.IsGhost) { BoundVar bv = arguments[m]; // FormalType f0 = ((Dt_Ctor0)source._D).a0; - Indent(indent + IndentAmount); + Indent(indent + IndentAmount, wr); wr.WriteLine("{0} @{1} = (({2}){3}._D).@{4};", - TypeName(bv.Type), bv.CompileName, DtCtorName(ctor, sourceType.TypeArgs), source, FormalName(arg, k)); + TypeName(bv.Type, wr), bv.CompileName, DtCtorName(ctor, sourceType.TypeArgs, wr), source, FormalName(arg, k)); k++; } } @@ -2229,51 +2243,51 @@ namespace Microsoft.Dafny { /// /// Before calling TrParenExpr(expr), the caller must have spilled the let variables declared in "expr". /// - void TrParenExpr(string prefix, Expression expr) { + void TrParenExpr(string prefix, Expression expr, TextWriter wr, bool inLetExprBody) { Contract.Requires(prefix != null); Contract.Requires(expr != null); wr.Write(prefix); - TrParenExpr(expr); + TrParenExpr(expr, wr, inLetExprBody); } /// /// Before calling TrParenExpr(expr), the caller must have spilled the let variables declared in "expr". /// - void TrParenExpr(Expression expr) { + void TrParenExpr(Expression expr, TextWriter wr, bool inLetExprBody) { Contract.Requires(expr != null); wr.Write("("); - TrExpr(expr); + TrExpr(expr, wr, inLetExprBody); wr.Write(")"); } /// /// Before calling TrExprList(exprs), the caller must have spilled the let variables declared in expressions in "exprs". /// - void TrExprList(List/*!*/ exprs) { + void TrExprList(List/*!*/ exprs, TextWriter wr, bool inLetExprBody) { Contract.Requires(cce.NonNullElements(exprs)); wr.Write("("); string sep = ""; foreach (Expression e in exprs) { wr.Write(sep); - TrExpr(e); + TrExpr(e, wr, inLetExprBody); sep = ", "; } wr.Write(")"); } - void TrExprPairList(List/*!*/ exprs) { + void TrExprPairList(List/*!*/ exprs, TextWriter wr, bool inLetExprBody) { Contract.Requires(cce.NonNullElements(exprs)); wr.Write("("); string sep = ""; foreach (ExpressionPair p in exprs) { wr.Write(sep); wr.Write("new Dafny.Pair<"); - wr.Write(TypeName(p.A.Type)); + wr.Write(TypeName(p.A.Type, wr)); wr.Write(","); - wr.Write(TypeName(p.B.Type)); + wr.Write(TypeName(p.B.Type, wr)); wr.Write(">("); - TrExpr(p.A); + TrExpr(p.A, wr, inLetExprBody); wr.Write(","); - TrExpr(p.B); + TrExpr(p.B, wr, inLetExprBody); wr.Write(")"); sep = ", "; } @@ -2283,13 +2297,13 @@ namespace Microsoft.Dafny { /// /// Before calling TrExpr(expr), the caller must have spilled the let variables declared in "expr". /// - void TrExpr(Expression expr) + void TrExpr(Expression expr, TextWriter wr, bool inLetExprBody) { Contract.Requires(expr != null); if (expr is LiteralExpr) { LiteralExpr e = (LiteralExpr)expr; if (e.Value == null) { - wr.Write("({0})null", TypeName(e.Type)); + wr.Write("({0})null", TypeName(e.Type, wr)); } else if (e.Value is bool) { wr.Write((bool)e.Value ? "true" : "false"); } else if (e is CharLiteralExpr) { @@ -2330,41 +2344,49 @@ namespace Microsoft.Dafny { } else if (expr is IdentifierExpr) { var e = (IdentifierExpr)expr; - wr.Write("@" + e.Var.CompileName); - + if (e.Var is Formal && inLetExprBody && !((Formal)e.Var).InParam) { + // out param in letExpr body, need to copy it to a temp since + // letExpr body is translated to an anonymous function that doesn't + // allow out parameters + var name = string.Format("_pat_let_tv{0}", GetUniqueAstNumber(e)); + wr.Write("@" + name); + copyInstrWriter.Append("var @" + name + "= @" + e.Var.CompileName + ";\n"); + } else { + wr.Write("@" + e.Var.CompileName); + } } else if (expr is SetDisplayExpr) { var e = (SetDisplayExpr)expr; var elType = e.Type.AsSetType.Arg; - wr.Write("{0}<{1}>.FromElements", DafnySetClass, TypeName(elType)); - TrExprList(e.Elements); + wr.Write("{0}<{1}>.FromElements", DafnySetClass, TypeName(elType, wr)); + TrExprList(e.Elements, wr, inLetExprBody); } else if (expr is MultiSetDisplayExpr) { var e = (MultiSetDisplayExpr)expr; var elType = e.Type.AsMultiSetType.Arg; - wr.Write("{0}<{1}>.FromElements", DafnyMultiSetClass, TypeName(elType)); - TrExprList(e.Elements); + wr.Write("{0}<{1}>.FromElements", DafnyMultiSetClass, TypeName(elType, wr)); + TrExprList(e.Elements, wr, inLetExprBody); } else if (expr is SeqDisplayExpr) { var e = (SeqDisplayExpr)expr; var elType = e.Type.AsSeqType.Arg; - wr.Write("{0}<{1}>.FromElements", DafnySeqClass, TypeName(elType)); - TrExprList(e.Elements); + wr.Write("{0}<{1}>.FromElements", DafnySeqClass, TypeName(elType, wr)); + TrExprList(e.Elements, wr, inLetExprBody); } else if (expr is MapDisplayExpr) { MapDisplayExpr e = (MapDisplayExpr)expr; - wr.Write("{0}.FromElements", TypeName(e.Type)); - TrExprPairList(e.Elements); + wr.Write("{0}.FromElements", TypeName(e.Type, wr)); + TrExprPairList(e.Elements, wr, inLetExprBody); } else if (expr is MemberSelectExpr) { MemberSelectExpr e = (MemberSelectExpr)expr; SpecialField sf = e.Member as SpecialField; if (sf != null) { wr.Write(sf.PreString); - TrParenExpr(e.Obj); + TrParenExpr(e.Obj, wr, inLetExprBody); wr.Write(".@{0}", sf.CompiledName); wr.Write(sf.PostString); } else { - TrParenExpr(e.Obj); + TrParenExpr(e.Obj, wr, inLetExprBody); wr.Write(".@{0}", e.Member.CompileName); } @@ -2374,50 +2396,50 @@ namespace Microsoft.Dafny { if (e.Seq.Type.IsArrayType) { if (e.SelectOne) { Contract.Assert(e.E0 != null && e.E1 == null); - TrParenExpr(e.Seq); + TrParenExpr(e.Seq, wr, inLetExprBody); wr.Write("[(int)"); - TrParenExpr(e.E0); + TrParenExpr(e.E0, wr, inLetExprBody); wr.Write("]"); } else { - TrParenExpr("Dafny.Helpers.SeqFromArray", e.Seq); + TrParenExpr("Dafny.Helpers.SeqFromArray", e.Seq, wr, inLetExprBody); if (e.E1 != null) { - TrParenExpr(".Take", e.E1); + TrParenExpr(".Take", e.E1, wr, inLetExprBody); } if (e.E0 != null) { - TrParenExpr(".Drop", e.E0); + TrParenExpr(".Drop", e.E0, wr, inLetExprBody); } } } else if (e.SelectOne) { Contract.Assert(e.E0 != null && e.E1 == null); - TrParenExpr(e.Seq); - TrParenExpr(".Select", e.E0); + TrParenExpr(e.Seq, wr, inLetExprBody); + TrParenExpr(".Select", e.E0, wr, inLetExprBody); } else { - TrParenExpr(e.Seq); + TrParenExpr(e.Seq, wr, inLetExprBody); if (e.E1 != null) { - TrParenExpr(".Take", e.E1); + TrParenExpr(".Take", e.E1, wr, inLetExprBody); } if (e.E0 != null) { - TrParenExpr(".Drop", e.E0); + TrParenExpr(".Drop", e.E0, wr, inLetExprBody); } } } else if (expr is MultiSetFormingExpr) { var e = (MultiSetFormingExpr)expr; - wr.Write("{0}<{1}>", DafnyMultiSetClass, TypeName(e.E.Type.AsCollectionType.Arg)); + wr.Write("{0}<{1}>", DafnyMultiSetClass, TypeName(e.E.Type.AsCollectionType.Arg, wr)); var eeType = e.E.Type.NormalizeExpand(); if (eeType is SeqType) { - TrParenExpr(".FromSeq", e.E); + TrParenExpr(".FromSeq", e.E, wr, inLetExprBody); } else if (eeType is SetType) { - TrParenExpr(".FromSet", e.E); + TrParenExpr(".FromSet", e.E, wr, inLetExprBody); } else { Contract.Assert(false); throw new cce.UnreachableException(); } } else if (expr is MultiSelectExpr) { MultiSelectExpr e = (MultiSelectExpr)expr; - TrParenExpr(e.Array); + TrParenExpr(e.Array, wr, inLetExprBody); string prefix = "["; foreach (Expression idx in e.Indices) { wr.Write("{0}(int)", prefix); - TrParenExpr(idx); + TrParenExpr(idx, wr, inLetExprBody); prefix = ", "; } wr.Write("]"); @@ -2426,47 +2448,47 @@ namespace Microsoft.Dafny { SeqUpdateExpr e = (SeqUpdateExpr)expr; if (e.ResolvedUpdateExpr != null) { - TrExpr(e.ResolvedUpdateExpr); + TrExpr(e.ResolvedUpdateExpr, wr, inLetExprBody); } else { - TrParenExpr(e.Seq); + TrParenExpr(e.Seq, wr, inLetExprBody); wr.Write(".Update("); - TrExpr(e.Index); + TrExpr(e.Index, wr, inLetExprBody); wr.Write(", "); - TrExpr(e.Value); + TrExpr(e.Value, wr, inLetExprBody); wr.Write(")"); } } else if (expr is FunctionCallExpr) { FunctionCallExpr e = (FunctionCallExpr)expr; - CompileFunctionCallExpr(e, wr, TrExpr); + CompileFunctionCallExpr(e, wr, wr, inLetExprBody, TrExpr); } else if (expr is ApplyExpr) { var e = expr as ApplyExpr; wr.Write("Dafny.Helpers.Id<"); - wr.Write(TypeName(e.Function.Type)); + wr.Write(TypeName(e.Function.Type, wr)); wr.Write(">("); - TrExpr(e.Function); + TrExpr(e.Function, wr, inLetExprBody); wr.Write(")"); - TrExprList(e.Args); + TrExprList(e.Args, wr, inLetExprBody); } else if (expr is DatatypeValue) { DatatypeValue dtv = (DatatypeValue)expr; Contract.Assert(dtv.Ctor != null); // since dtv has been successfully resolved - var typeParams = dtv.InferredTypeArgs.Count == 0 ? "" : string.Format("<{0}>", TypeNames(dtv.InferredTypeArgs)); + var typeParams = dtv.InferredTypeArgs.Count == 0 ? "" : string.Format("<{0}>", TypeNames(dtv.InferredTypeArgs, wr)); wr.Write("new {0}{1}(", DtName(dtv.Ctor.EnclosingDatatype), typeParams); if (!dtv.IsCoCall) { // For an ordinary constructor (that is, one that does not guard any co-recursive calls), generate: // new Dt_Cons( args ) - wr.Write("new {0}(", DtCtorName(dtv.Ctor, dtv.InferredTypeArgs)); + wr.Write("new {0}(", DtCtorName(dtv.Ctor, dtv.InferredTypeArgs, wr)); string sep = ""; for (int i = 0; i < dtv.Arguments.Count; i++) { Formal formal = dtv.Ctor.Formals[i]; if (!formal.IsGhost) { wr.Write(sep); - TrExpr(dtv.Arguments[i]); + TrExpr(dtv.Arguments[i], wr, inLetExprBody); sep = ", "; } } @@ -2495,17 +2517,17 @@ namespace Microsoft.Dafny { arg = varName; wr.Write("var {0} = ", varName); - TrExpr(actual); + TrExpr(actual, wr, inLetExprBody); wr.Write("; "); } else { var sw = new StringWriter(); - CompileFunctionCallExpr(fce, sw, (exp) => { + CompileFunctionCallExpr(fce, sw, wr, inLetExprBody, (exp, wrr, inLetExpr) => { string varName = idGenerator.FreshId("_ac"); sw.Write(varName); - wr.Write("var {0} = ", varName); - TrExpr(exp); - wr.Write("; "); + wrr.Write("var {0} = ", varName); + TrExpr(exp, wrr, inLetExpr); + wrr.Write("; "); }); arg = sw.ToString(); @@ -2517,7 +2539,7 @@ namespace Microsoft.Dafny { wr.Write("return () => { return "); - wr.Write("new {0}({1}", DtCtorName(dtv.Ctor, dtv.InferredTypeArgs), args); + wr.Write("new {0}({1}", DtCtorName(dtv.Ctor, dtv.InferredTypeArgs, wr), args); wr.Write("); }; })())"); } wr.Write(")"); @@ -2530,11 +2552,11 @@ namespace Microsoft.Dafny { switch (e.Op) { case UnaryOpExpr.Opcode.Not: wr.Write("!"); - TrParenExpr(e.E); + TrParenExpr(e.E, wr, inLetExprBody); break; case UnaryOpExpr.Opcode.Cardinality: wr.Write("new BigInteger("); - TrParenExpr(e.E); + TrParenExpr(e.E, wr, inLetExprBody); wr.Write(".Length)"); break; default: @@ -2552,7 +2574,7 @@ namespace Microsoft.Dafny { if (AsNativeType(e.E.Type) != null) { wr.Write("new BigInteger"); } - TrParenExpr(e.E); + TrParenExpr(e.E, wr, inLetExprBody); }; Action toIntCast = () => { Contract.Assert(toInt); @@ -2568,7 +2590,7 @@ namespace Microsoft.Dafny { } else if (!fromInt && toInt) { // real -> int toIntCast(); - TrParenExpr(e.E); + TrParenExpr(e.E, wr, inLetExprBody); wr.Write(".ToBigInteger()"); } else if (AsNativeType(e.ToType) != null) { toIntCast(); @@ -2580,14 +2602,14 @@ namespace Microsoft.Dafny { wr.Write("(" + (BigInteger)lit.Value + AsNativeType(e.ToType).Suffix + ")"); } else if ((u != null && u.Op == UnaryOpExpr.Opcode.Cardinality) || (m != null && m.MemberName == "Length" && m.Obj.Type.IsArrayType)) { // Optimize .Length to avoid intermediate BigInteger - TrParenExpr((u != null) ? u.E : m.Obj); + TrParenExpr((u != null) ? u.E : m.Obj, wr, inLetExprBody); if (AsNativeType(e.ToType).UpperBound <= new BigInteger(0x80000000U)) { wr.Write(".Length"); } else { wr.Write(".LongLength"); } } else { - TrParenExpr(e.E); + TrParenExpr(e.E, wr, inLetExprBody); } } else if (e.ToType.IsIntegerType && AsNativeType(e.E.Type) != null) { fromIntAsBigInteger(); @@ -2595,7 +2617,7 @@ namespace Microsoft.Dafny { Contract.Assert(fromInt == toInt); Contract.Assert(AsNativeType(e.ToType) == null); Contract.Assert(AsNativeType(e.E.Type) == null); - TrParenExpr(e.E); + TrParenExpr(e.E, wr, inLetExprBody); } } else if (expr is BinaryExpr) { @@ -2664,9 +2686,9 @@ namespace Microsoft.Dafny { if (expr.Type.IsIntegerType || (AsNativeType(expr.Type) != null && AsNativeType(expr.Type).LowerBound < BigInteger.Zero)) { string suffix = AsNativeType(expr.Type) != null ? ("_" + AsNativeType(expr.Type).Name) : ""; wr.Write("Dafny.Helpers.EuclideanDivision" + suffix + "("); - TrParenExpr(e.E0); + TrParenExpr(e.E0, wr, inLetExprBody); wr.Write(", "); - TrExpr(e.E1); + TrExpr(e.E1, wr, inLetExprBody); wr.Write(")"); } else { opString = "/"; // for reals @@ -2676,9 +2698,9 @@ namespace Microsoft.Dafny { if (expr.Type.IsIntegerType || (AsNativeType(expr.Type) != null && AsNativeType(expr.Type).LowerBound < BigInteger.Zero)) { string suffix = AsNativeType(expr.Type) != null ? ("_" + AsNativeType(expr.Type).Name) : ""; wr.Write("Dafny.Helpers.EuclideanModulus" + suffix + "("); - TrParenExpr(e.E0); + TrParenExpr(e.E0, wr, inLetExprBody); wr.Write(", "); - TrExpr(e.E1); + TrExpr(e.E1, wr, inLetExprBody); wr.Write(")"); } else { opString = "%"; // for reals @@ -2713,18 +2735,18 @@ namespace Microsoft.Dafny { case BinaryExpr.ResolvedOpcode.InSet: case BinaryExpr.ResolvedOpcode.InMultiSet: case BinaryExpr.ResolvedOpcode.InMap: - TrParenExpr(e.E1); + TrParenExpr(e.E1, wr, inLetExprBody); wr.Write(".Contains("); - TrExpr(e.E0); + TrExpr(e.E0, wr, inLetExprBody); wr.Write(")"); break; case BinaryExpr.ResolvedOpcode.NotInSet: case BinaryExpr.ResolvedOpcode.NotInMultiSet: case BinaryExpr.ResolvedOpcode.NotInMap: wr.Write("!"); - TrParenExpr(e.E1); + TrParenExpr(e.E1, wr, inLetExprBody); wr.Write(".Contains("); - TrExpr(e.E0); + TrExpr(e.E0, wr, inLetExprBody); wr.Write(")"); break; case BinaryExpr.ResolvedOpcode.Union: @@ -2744,16 +2766,16 @@ namespace Microsoft.Dafny { case BinaryExpr.ResolvedOpcode.Concat: callString = "Concat"; break; case BinaryExpr.ResolvedOpcode.InSeq: - TrParenExpr(e.E1); + TrParenExpr(e.E1, wr, inLetExprBody); wr.Write(".Contains("); - TrExpr(e.E0); + TrExpr(e.E0, wr, inLetExprBody); wr.Write(")"); break; case BinaryExpr.ResolvedOpcode.NotInSeq: wr.Write("!"); - TrParenExpr(e.E1); + TrParenExpr(e.E1, wr, inLetExprBody); wr.Write(".Contains("); - TrExpr(e.E0); + TrExpr(e.E0, wr, inLetExprBody); wr.Write(")"); break; @@ -2767,17 +2789,17 @@ namespace Microsoft.Dafny { wr.Write("(" + nativeType.Name + ")("); } wr.Write(preOpString); - TrParenExpr(e.E0); + TrParenExpr(e.E0, wr, inLetExprBody); wr.Write(" {0} ", opString); - TrParenExpr(e.E1); + TrParenExpr(e.E1, wr, inLetExprBody); if (needsCast) { wr.Write(")"); } } else if (callString != null) { wr.Write(preOpString); - TrParenExpr(e.E0); + TrParenExpr(e.E0, wr, inLetExprBody); wr.Write(".@{0}(", callString); - TrExpr(e.E1); + TrExpr(e.E1, wr, inLetExprBody); wr.Write(")"); } @@ -2800,17 +2822,18 @@ namespace Microsoft.Dafny { if (Contract.Exists(lhs.Vars, bv => !bv.IsGhost)) { var rhsName = string.Format("_pat_let{0}_{1}", GetUniqueAstNumber(e), i); wr.Write("Dafny.Helpers.Let<"); - wr.Write(TypeName(e.RHSs[i].Type) + "," + TypeName(e.Body.Type)); + wr.Write(TypeName(e.RHSs[i].Type, wr) + "," + TypeName(e.Body.Type, wr)); wr.Write(">("); - TrExpr(e.RHSs[i]); + TrExpr(e.RHSs[i], wr, inLetExprBody); wr.Write(", " + rhsName + " => "); neededCloseParens++; - var c = TrCasePattern(lhs, rhsName, e.Body.Type); + var c = TrCasePattern(lhs, rhsName, e.Body.Type, wr); Contract.Assert(c != 0); // we already checked that there's at least one non-ghost neededCloseParens += c; } } - TrExpr(e.Body); + + TrExpr(e.Body, wr, true); for (int i = 0; i < neededCloseParens; i++) { wr.Write(")"); } @@ -2819,7 +2842,7 @@ namespace Microsoft.Dafny { // ghost var x,y :| Constraint; E // is compiled just like E is, because the resolver has already checked that x,y (or other ghost variables, for that matter) don't // occur in E (moreover, the verifier has checked that values for x,y satisfying Constraint exist). - TrExpr(e.Body); + TrExpr(e.Body, wr, inLetExprBody); } else { // The Dafny "let" expression // var x,y :| Constraint; E @@ -2834,17 +2857,17 @@ namespace Microsoft.Dafny { Contract.Assert(e.RHSs.Count == 1); // checked by resolution if (e.Constraint_MissingBounds != null) { foreach (var bv in e.Constraint_MissingBounds) { - Error("this let-such-that expression is too advanced for the current compiler; Dafny's heuristics cannot find any bound for variable '{0}' (line {1})", bv.Name, e.tok.line); + Error("this let-such-that expression is too advanced for the current compiler; Dafny's heuristics cannot find any bound for variable '{0}' (line {1})", wr, bv.Name, e.tok.line); } } else { - wr.Write("Dafny.Helpers.Let(0, _let_dummy_" + GetUniqueAstNumber(e) + " => {"); + wr.Write("Dafny.Helpers.Let(0, _let_dummy_" + GetUniqueAstNumber(e) + " => {"); foreach (var bv in e.BoundVars) { - wr.Write("{0} @{1}", TypeName(bv.Type), bv.CompileName); - wr.WriteLine(" = {0};", DefaultValue(bv.Type)); + wr.Write("{0} @{1}", TypeName(bv.Type, wr), bv.CompileName); + wr.WriteLine(" = {0};", DefaultValue(bv.Type, wr)); } - TrAssignSuchThat(0, new List(e.BoundVars).ConvertAll(bv => (IVariable)bv), e.RHSs[0], e.Constraint_Bounds, e.tok.line); + TrAssignSuchThat(0, new List(e.BoundVars).ConvertAll(bv => (IVariable)bv), e.RHSs[0], e.Constraint_Bounds, e.tok.line, wr, inLetExprBody); wr.Write(" return "); - TrExpr(e.Body); + TrExpr(e.Body, wr, true); wr.Write("; })"); } } @@ -2864,7 +2887,7 @@ namespace Microsoft.Dafny { // }(src) string source = idGenerator.FreshId("_source"); - wr.Write("new Dafny.Helpers.Function<{0}, {1}>(delegate ({0} {2}) {{ ", TypeName(e.Source.Type), TypeName(e.Type), source); + wr.Write("new Dafny.Helpers.Function<{0}, {1}>(delegate ({0} {2}) {{ ", TypeName(e.Source.Type, wr), TypeName(e.Type, wr), source); if (e.Cases.Count == 0) { // the verifier would have proved we never get here; still, we need some code that will compile @@ -2873,9 +2896,9 @@ namespace Microsoft.Dafny { int i = 0; var sourceType = (UserDefinedType)e.Source.Type.NormalizeExpand(); foreach (MatchCaseExpr mc in e.Cases) { - MatchCasePrelude(source, sourceType, cce.NonNull(mc.Ctor), mc.Arguments, i, e.Cases.Count, 0); + MatchCasePrelude(source, sourceType, cce.NonNull(mc.Ctor), mc.Arguments, i, e.Cases.Count, 0, wr); wr.Write("return "); - TrExpr(mc.Body); + TrExpr(mc.Body, wr, inLetExprBody); wr.Write("; "); i++; } @@ -2883,7 +2906,7 @@ namespace Microsoft.Dafny { } // We end with applying the source expression to the delegate we just built wr.Write("})("); - TrExpr(e.Source); + TrExpr(e.Source, wr, inLetExprBody); wr.Write(")"); } else if (expr is QuantifierExpr) { @@ -2905,24 +2928,24 @@ namespace Microsoft.Dafny { } else if (bound is ComprehensionExpr.IntBoundedPool) { var b = (ComprehensionExpr.IntBoundedPool)bound; wr.Write("Dafny.Helpers.QuantInt("); - TrExpr(b.LowerBound); + TrExpr(b.LowerBound, wr, inLetExprBody); wr.Write(", "); - TrExpr(b.UpperBound); + TrExpr(b.UpperBound, wr, inLetExprBody); wr.Write(", "); } else if (bound is ComprehensionExpr.SetBoundedPool) { var b = (ComprehensionExpr.SetBoundedPool)bound; wr.Write("Dafny.Helpers.QuantSet("); - TrExpr(b.Set); + TrExpr(b.Set, wr, inLetExprBody); wr.Write(", "); } else if (bound is ComprehensionExpr.MapBoundedPool) { var b = (ComprehensionExpr.MapBoundedPool)bound; wr.Write("Dafny.Helpers.QuantMap("); - TrExpr(b.Map); + TrExpr(b.Map, wr, inLetExprBody); wr.Write(", "); } else if (bound is ComprehensionExpr.SeqBoundedPool) { var b = (ComprehensionExpr.SeqBoundedPool)bound; wr.Write("Dafny.Helpers.QuantSeq("); - TrExpr(b.Seq); + TrExpr(b.Seq, wr, inLetExprBody); wr.Write(", "); } else if (bound is ComprehensionExpr.DatatypeBoundedPool) { var b = (ComprehensionExpr.DatatypeBoundedPool)bound; @@ -2935,7 +2958,7 @@ namespace Microsoft.Dafny { wr.Write("{0}, ", expr is ForallExpr ? "true" : "false"); wr.Write("@{0} => ", bv.CompileName); } - TrExpr(e.LogicalBody(true)); + TrExpr(e.LogicalBody(true), wr, inLetExprBody); for (int i = 0; i < n; i++) { wr.Write(")"); } @@ -2959,7 +2982,7 @@ namespace Microsoft.Dafny { // return Dafny.Set.FromCollection(_coll); // })() Contract.Assert(e.Bounds != null); // the resolver would have insisted on finding bounds - var typeName = TypeName(e.Type.AsSetType.Arg); + var typeName = TypeName(e.Type.AsSetType.Arg, wr); wr.Write("((Dafny.Helpers.ComprehensionDelegate<{0}>)delegate() {{ ", typeName); wr.Write("var _coll = new System.Collections.Generic.List<{0}>(); ", typeName); var n = e.BoundVars.Count; @@ -2978,36 +3001,36 @@ namespace Microsoft.Dafny { } else { wr.Write("foreach (var @{0} in Dafny.Helpers.IntegerRange(", bv.CompileName); } - TrExpr(b.LowerBound); + TrExpr(b.LowerBound, wr, inLetExprBody); wr.Write(", "); - TrExpr(b.UpperBound); + TrExpr(b.UpperBound, wr, inLetExprBody); wr.Write(")) { "); } else if (bound is ComprehensionExpr.SetBoundedPool) { var b = (ComprehensionExpr.SetBoundedPool)bound; wr.Write("foreach (var @{0} in (", bv.CompileName); - TrExpr(b.Set); + TrExpr(b.Set, wr, inLetExprBody); wr.Write(").Elements) { "); } else if (bound is ComprehensionExpr.MapBoundedPool) { var b = (ComprehensionExpr.MapBoundedPool)bound; wr.Write("foreach (var @{0} in (", bv.CompileName); - TrExpr(b.Map); + TrExpr(b.Map, wr, inLetExprBody); wr.Write(").Domain) { "); } else if (bound is ComprehensionExpr.SeqBoundedPool) { var b = (ComprehensionExpr.SeqBoundedPool)bound; wr.Write("foreach (var @{0} in (", bv.CompileName); - TrExpr(b.Seq); + TrExpr(b.Seq, wr, inLetExprBody); wr.Write(").Elements) { "); } else if (bound is ComprehensionExpr.DatatypeBoundedPool) { var b = (ComprehensionExpr.DatatypeBoundedPool)bound; - wr.Write("foreach (var @{0} in {1}.AllSingletonConstructors) {{", bv.CompileName, TypeName(bv.Type)); + wr.Write("foreach (var @{0} in {1}.AllSingletonConstructors) {{", bv.CompileName, TypeName(bv.Type, wr)); } else { Contract.Assert(false); throw new cce.UnreachableException(); // unexpected BoundedPool type } } wr.Write("if ("); - TrExpr(e.Range); + TrExpr(e.Range, wr, inLetExprBody); wr.Write(") { _coll.Add("); - TrExpr(e.Term); + TrExpr(e.Term, wr, inLetExprBody); wr.Write("); }"); for (int i = 0; i < n; i++) { wr.Write("}"); @@ -3034,8 +3057,8 @@ namespace Microsoft.Dafny { // return Dafny.Map.FromElements(_coll); // })() Contract.Assert(e.Bounds != null); // the resolver would have insisted on finding bounds - var domtypeName = TypeName(e.Type.AsMapType.Domain); - var rantypeName = TypeName(e.Type.AsMapType.Range); + var domtypeName = TypeName(e.Type.AsMapType.Domain, wr); + var rantypeName = TypeName(e.Type.AsMapType.Range, wr); wr.Write("((Dafny.Helpers.MapComprehensionDelegate<{0},{1}>)delegate() {{ ", domtypeName, rantypeName); wr.Write("var _coll = new System.Collections.Generic.List>(); ", domtypeName, rantypeName); var n = e.BoundVars.Count; @@ -3053,34 +3076,34 @@ namespace Microsoft.Dafny { } else { wr.Write("foreach (var @{0} in Dafny.Helpers.IntegerRange(", bv.CompileName); } - TrExpr(b.LowerBound); + TrExpr(b.LowerBound, wr, inLetExprBody); wr.Write(", "); - TrExpr(b.UpperBound); + TrExpr(b.UpperBound, wr, inLetExprBody); wr.Write(")) { "); } else if (bound is ComprehensionExpr.SetBoundedPool) { var b = (ComprehensionExpr.SetBoundedPool)bound; wr.Write("foreach (var @{0} in (", bv.CompileName); - TrExpr(b.Set); + TrExpr(b.Set, wr, inLetExprBody); wr.Write(").Elements) { "); } else if (bound is ComprehensionExpr.MapBoundedPool) { var b = (ComprehensionExpr.MapBoundedPool)bound; wr.Write("foreach (var @{0} in (", bv.CompileName); - TrExpr(b.Map); + TrExpr(b.Map, wr, inLetExprBody); wr.Write(").Domain) { "); } else if (bound is ComprehensionExpr.SeqBoundedPool) { var b = (ComprehensionExpr.SeqBoundedPool)bound; wr.Write("foreach (var @{0} in (", bv.CompileName); - TrExpr(b.Seq); + TrExpr(b.Seq, wr, inLetExprBody); wr.Write(").Elements) { "); } else { // TODO: handle ComprehensionExpr.SubSetBoundedPool Contract.Assert(false); throw new cce.UnreachableException(); // unexpected BoundedPool type } wr.Write("if ("); - TrExpr(e.Range); + TrExpr(e.Range, wr, inLetExprBody); wr.Write(") { "); wr.Write("_coll.Add(new Dafny.Pair<{0},{1}>(@{2},", domtypeName, rantypeName, bv.CompileName); - TrExpr(e.Term); + TrExpr(e.Term, wr, inLetExprBody); wr.Write(")); }"); wr.Write("}"); wr.Write("return Dafny.Map<{0},{1}>.FromCollection(_coll); ", domtypeName, rantypeName); @@ -3109,46 +3132,46 @@ namespace Microsoft.Dafny { var su = new Translator.Substituter(null, sm, new Dictionary(), null); - BetaRedex(bvars, fexprs, expr.Type, () => { + BetaRedex(bvars, fexprs, expr.Type, wr, inLetExprBody, () => { wr.Write("("); wr.Write(Util.Comma(e.BoundVars, bv => "@" + bv.CompileName)); wr.Write(") => "); - TrExpr(su.Substitute(e.Body)); + TrExpr(su.Substitute(e.Body), wr, inLetExprBody); }); } else if (expr is StmtExpr) { var e = (StmtExpr)expr; - TrExpr(e.E); + TrExpr(e.E, wr, inLetExprBody); } else if (expr is ITEExpr) { ITEExpr e = (ITEExpr)expr; wr.Write("("); - TrExpr(e.Test); + TrExpr(e.Test, wr, inLetExprBody); wr.Write(") ? ("); - TrExpr(e.Thn); + TrExpr(e.Thn, wr, inLetExprBody); wr.Write(") : ("); - TrExpr(e.Els); + TrExpr(e.Els, wr, inLetExprBody); wr.Write(")"); } else if (expr is ConcreteSyntaxExpression) { var e = (ConcreteSyntaxExpression)expr; - TrExpr(e.ResolvedExpression); + TrExpr(e.ResolvedExpression, wr, inLetExprBody); } else if (expr is NamedExpr) { - TrExpr(((NamedExpr)expr).Body); + TrExpr(((NamedExpr)expr).Body, wr, inLetExprBody); } else { Contract.Assert(false); throw new cce.UnreachableException(); // unexpected expression } } - int TrCasePattern(CasePattern pat, string rhsString, Type bodyType) { + int TrCasePattern(CasePattern pat, string rhsString, Type bodyType, TextWriter wr) { Contract.Requires(pat != null); Contract.Requires(rhsString != null); int c = 0; if (pat.Var != null) { var bv = pat.Var; if (!bv.IsGhost) { - wr.Write("Dafny.Helpers.Let<" + TypeName(bv.Type) + "," + TypeName(bodyType) + ">"); + wr.Write("Dafny.Helpers.Let<" + TypeName(bv.Type, wr) + "," + TypeName(bodyType, wr) + ">"); wr.Write("(" + rhsString + ", @" + bv.CompileName + " => "); c++; } @@ -3164,7 +3187,7 @@ namespace Microsoft.Dafny { // nothing to compile, but do a sanity check Contract.Assert(!Contract.Exists(arg.Vars, bv => !bv.IsGhost)); } else { - c += TrCasePattern(arg, string.Format("(({0})({1})._D).@{2}", DtCtorName(ctor, ((DatatypeValue)pat.Expr).InferredTypeArgs), rhsString, FormalName(formal, k)), bodyType); + c += TrCasePattern(arg, string.Format("(({0})({1})._D).@{2}", DtCtorName(ctor, ((DatatypeValue)pat.Expr).InferredTypeArgs, wr), rhsString, FormalName(formal, k)), bodyType, wr); k++; } } @@ -3172,40 +3195,40 @@ namespace Microsoft.Dafny { return c; } - delegate void FCE_Arg_Translator(Expression e); + delegate void FCE_Arg_Translator(Expression e, TextWriter wr, bool inLetExpr=false); - void CompileFunctionCallExpr(FunctionCallExpr e, TextWriter twr, FCE_Arg_Translator tr) { + void CompileFunctionCallExpr(FunctionCallExpr e, TextWriter twr, TextWriter wr, bool inLetExprBody, FCE_Arg_Translator tr) { Function f = cce.NonNull(e.Function); if (f.IsStatic) { - twr.Write(TypeName_Companion(e.Receiver.Type)); + twr.Write(TypeName_Companion(e.Receiver.Type, wr)); } else { twr.Write("("); - tr(e.Receiver); + tr(e.Receiver, wr, inLetExprBody); twr.Write(")"); } twr.Write(".@{0}", f.CompileName); if (f.TypeArgs.Count != 0) { List typeArgs = f.TypeArgs.ConvertAll(ta => e.TypeArgumentSubstitutions[ta]); - twr.Write("<" + TypeNames(typeArgs) + ">"); + twr.Write("<" + TypeNames(typeArgs, wr) + ">"); } twr.Write("("); string sep = ""; for (int i = 0; i < e.Args.Count; i++) { if (!e.Function.Formals[i].IsGhost) { twr.Write(sep); - tr(e.Args[i]); + tr(e.Args[i], wr); sep = ", "; } } twr.Write(")"); } - void BetaRedex(List bvars, List exprs, Type bodyType, Action makeBody) { + void BetaRedex(List bvars, List exprs, Type bodyType, TextWriter wr, bool inLetExprBody, Action makeBody) { Contract.Requires(bvars != null); Contract.Requires(exprs != null); Contract.Requires(bvars.Count == exprs.Count); wr.Write("Dafny.Helpers.Id<"); - wr.Write(TypeName_UDT(ArrowType.Arrow_FullCompileName, Util.Snoc(bvars.ConvertAll(bv => bv.Type), bodyType))); + wr.Write(TypeName_UDT(ArrowType.Arrow_FullCompileName, Util.Snoc(bvars.ConvertAll(bv => bv.Type), bodyType), wr)); wr.Write(">(("); wr.Write(Util.Comma(bvars, bv => "@" + bv.CompileName)); wr.Write(") => "); @@ -3213,7 +3236,7 @@ namespace Microsoft.Dafny { makeBody(); wr.Write(")"); - TrExprList(exprs); + TrExprList(exprs, wr, inLetExprBody); } } diff --git a/Source/DafnyDriver/DafnyDriver.cs b/Source/DafnyDriver/DafnyDriver.cs index 8282edc7..6cfbe7e1 100644 --- a/Source/DafnyDriver/DafnyDriver.cs +++ b/Source/DafnyDriver/DafnyDriver.cs @@ -300,14 +300,14 @@ namespace Microsoft.Dafny // Compile the Dafny program into a string that contains the C# program StringWriter sw = new StringWriter(); - Dafny.Compiler compiler = new Dafny.Compiler(sw); + 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); + compiler.Compile(dafnyProgram, sw); var csharpProgram = sw.ToString(); bool completeProgram = compiler.ErrorCount == 0; diff --git a/Test/dafny4/Bug89.dfy b/Test/dafny4/Bug89.dfy new file mode 100644 index 00000000..12aec5f4 --- /dev/null +++ b/Test/dafny4/Bug89.dfy @@ -0,0 +1,15 @@ +// RUN: %dafny /compile:3 "%s" > "%t" +// RUN: %diff "%s.expect" "%t" + +method F() returns(x:int) + ensures x == 6; +{ + x := 5; + x := (var y := 1; y + x); +} + +method Main() +{ + var x := F(); + print x; +} \ No newline at end of file diff --git a/Test/dafny4/Bug89.dfy.expect b/Test/dafny4/Bug89.dfy.expect new file mode 100644 index 00000000..5221a5d1 --- /dev/null +++ b/Test/dafny4/Bug89.dfy.expect @@ -0,0 +1,6 @@ + +Dafny program verifier finished with 4 verified, 0 errors +Program compiled successfully +Running... + +6 \ No newline at end of file -- cgit v1.2.3 From 17405efd598d2a8a2dac304ee9a7f7d9bd30a558 Mon Sep 17 00:00:00 2001 From: "Richard L. Ford" Date: Wed, 27 Jan 2016 14:09:16 -0800 Subject: Implement 'extern' declaration modifier. The 'extern' declaration modifier provides a more convenient way of interfacing Dafny code with C# source files and .Net DLLs. We support an 'extern' keyword on a module, class, function method, or method (cannot extern ghost). We check the CompileNames of all modules to make sure there are no duplicate names. Every Dafny-generated C# class is marked partial, so it can potentially be extended. The extern keyword could be accompanied by an optional string naming the corresponding C# method/class to connect to. If not given the name of the method/class is used. An 'extern' keyword implies an {:axiom} attribute for functions and methods, so their ensures clauses are assumed to be true without proof. In addition to the .dfy files, the user may supply C# files (.cs) and dynamic linked libraries (.dll) on command line. These will be passed onto the C# compiler, the .cs files as sources, and the .dll files as references. As part of this change the grammar was refactored some. New productions are - TopDecls - a list of top-level declarations. - TopDecl - a single top-level declaration - DeclModifiers - a list of declaration modifiers which are either 'abstract', 'ghost', 'static', 'protected', or 'extern'. They can be in any order and we diagnose duplicates. In addition, since they are not all allowed in all contexts, we check and give diagnostics if an DeclModifier appears where it is not allowed. --- Source/Dafny/Compiler.cs | 2 +- Source/Dafny/Dafny.atg | 356 +++++--- Source/Dafny/DafnyAst.cs | 31 +- Source/Dafny/Makefile | 4 +- Source/Dafny/Parser.cs | 1534 ++++++++++++++++++--------------- Source/Dafny/Resolver.cs | 29 + Source/Dafny/Scanner.cs | 169 ++-- Source/DafnyDriver/DafnyDriver.cs | 121 ++- Source/DafnyExtension/DafnyDriver.cs | 6 +- Test/dafny0/Extern.dfy | 27 + Test/dafny0/Extern.dfy.expect | 4 + Test/dafny0/Extern2.cs | 14 + Test/dafny0/ExternHelloLibrary.cs | 15 + Test/dafny0/ExternHelloLibrary.dll | Bin 0 -> 3072 bytes Test/dafny0/ExternNegative.dfy | 26 + Test/dafny0/ExternNegative.dfy.expect | 3 + Test/dafny0/ExternNegative2.dfy | 26 + 17 files changed, 1407 insertions(+), 960 deletions(-) create mode 100644 Test/dafny0/Extern.dfy create mode 100644 Test/dafny0/Extern.dfy.expect create mode 100644 Test/dafny0/Extern2.cs create mode 100644 Test/dafny0/ExternHelloLibrary.cs create mode 100644 Test/dafny0/ExternHelloLibrary.dll create mode 100644 Test/dafny0/ExternNegative.dfy create mode 100644 Test/dafny0/ExternNegative.dfy.expect create mode 100644 Test/dafny0/ExternNegative2.dfy (limited to 'Source/DafnyDriver/DafnyDriver.cs') diff --git a/Source/Dafny/Compiler.cs b/Source/Dafny/Compiler.cs index 1a99a8af..f5f95bd2 100644 --- a/Source/Dafny/Compiler.cs +++ b/Source/Dafny/Compiler.cs @@ -254,7 +254,7 @@ namespace Microsoft.Dafny { else if (d is ClassDecl) { var cl = (ClassDecl)d; Indent(indent, wr); - wr.Write("public class @{0}", cl.CompileName); + wr.Write("public partial class @{0}", cl.CompileName); if (cl.TypeArgs.Count != 0) { wr.Write("<{0}>", TypeParameters(cl.TypeArgs)); } diff --git a/Source/Dafny/Dafny.atg b/Source/Dafny/Dafny.atg index 08c22db4..87e75541 100644 --- a/Source/Dafny/Dafny.atg +++ b/Source/Dafny/Dafny.atg @@ -23,10 +23,113 @@ readonly BuiltIns theBuiltIns; readonly bool theVerifyThisFile; int anonymousIds = 0; -struct MemberModifiers { +/// +/// Holds the modifiers given for a declaration +/// +/// Not all modifiers are applicable to all kinds of declarations. +/// Errors are given when a modify does not apply. +/// We also record the tokens for the specified modifiers so that +/// they can be used in error messages. +/// +struct DeclModifierData { + public bool IsAbstract; + public IToken AbstractToken; public bool IsGhost; + public IToken GhostToken; public bool IsStatic; + public IToken StaticToken; public bool IsProtected; + public IToken ProtectedToken; + public bool IsExtern; + public IToken ExternToken; + public StringLiteralExpr ExternName; + +} + +// Check that token has not been set, then set it. +public void CheckAndSetToken(ref IToken token) +{ + if (token != null) { + SemErr(t, "Duplicate declaration modifier: " + t.val); + } + token = t; +} + +/// +// A flags type used to tell what declaration modifiers are allowed for a declaration. +/// +[Flags] +enum AllowedDeclModifiers { + None = 0, + Abstract = 1, + Ghost = 2, + + // Means ghost not allowed because already implicitly ghost. + AlreadyGhost = 4, + Static = 8, + Protected = 16, + Extern = 32 +}; + +/// +/// Check the declaration modifiers against those that are allowed. +/// +/// The 'allowed' parameter specifies which declaratio modifiers are allowed. +/// The 'declCaption' parameter should be a string describing the kind of declaration. +/// It is used in error messages. +/// Any declaration modifiers that are present but not allowed are cleared. +/// +void CheckDeclModifiers(DeclModifierData dmod, string declCaption, AllowedDeclModifiers allowed) +{ + if (dmod.IsAbstract && ((allowed & AllowedDeclModifiers.Abstract) == 0)) { + SemErr(dmod.AbstractToken, declCaption + " cannot be declared 'abstract'."); + dmod.IsAbstract = false; + } + if (dmod.IsGhost) { + if ((allowed & AllowedDeclModifiers.AlreadyGhost) != 0) { + SemErr(dmod.GhostToken, declCaption + " cannot be declared ghost (they are 'ghost' by default)."); + dmod.IsGhost = false; + } else if ((allowed & AllowedDeclModifiers.Ghost) == 0) { + SemErr(dmod.GhostToken, declCaption + " cannot be declared 'ghost'."); + dmod.IsGhost = false; + } + } + if (dmod.IsStatic && ((allowed & AllowedDeclModifiers.Static) == 0)) { + SemErr(dmod.StaticToken, declCaption + " cannot be declared 'static'."); + dmod.IsStatic = false; + } + if (dmod.IsProtected && ((allowed & AllowedDeclModifiers.Protected) == 0)) { + SemErr(dmod.ProtectedToken, declCaption + " cannot be declared 'protected'."); + dmod.IsProtected = false; + } + if (dmod.IsExtern && ((allowed & AllowedDeclModifiers.Extern) == 0)) { + SemErr(dmod.ExternToken, declCaption + " cannot be declared 'extern'."); + dmod.IsExtern = false; + } +} + +/// +/// Encode an 'extern' declaration modifier as an {:extern name} attribute. +/// +/// We also include an {:axiom} attribute since the specification of an +/// external entity is assumed to hold, but only for methods or functions. +/// +static void EncodeExternAsAttribute(DeclModifierData dmod, ref Attributes attrs, IToken/*!*/ id, bool needAxiom) { + if (dmod.IsExtern) { + StringLiteralExpr name = dmod.ExternName; + if (name == null) { + bool isVerbatimString = false; + name = new StringLiteralExpr(id, id.val, isVerbatimString); + } + var args = new List(); + args.Add(name); + attrs = new Attributes("extern", args, attrs); + + // Also 'extern' implies 'axiom' for methods or functions. + if (needAxiom) { + attrs = new Attributes("axiom", new List(), attrs); + } + } } /// @@ -516,13 +619,10 @@ IGNORE cr + lf + tab /*------------------------------------------------------------------------*/ PRODUCTIONS Dafny -= (. ClassDecl/*!*/ c; DatatypeDecl/*!*/ dt; TopLevelDecl td; IteratorDecl iter; - List membersDefaultClass = new List(); - ModuleDecl submodule; += (. List membersDefaultClass = new List(); // to support multiple files, create a default module only if theModule is null DefaultModuleDecl defaultModule = (DefaultModuleDecl)((LiteralModuleDecl)theModule).ModuleDef; // theModule should be a DefaultModuleDecl (actually, the singular DefaultModuleDecl) - TraitDecl/*!*/ trait; Contract.Assert(defaultModule != null); .) { "include" stringToken (. { @@ -540,15 +640,7 @@ Dafny } .) } - { SubModuleDecl (. defaultModule.TopLevelDecls.Add(submodule); .) - | ClassDecl (. defaultModule.TopLevelDecls.Add(c); .) - | DatatypeDecl (. defaultModule.TopLevelDecls.Add(dt); .) - | NewtypeDecl (. defaultModule.TopLevelDecls.Add(td); .) - | OtherTypeDecl (. defaultModule.TopLevelDecls.Add(td); .) - | IteratorDecl (. defaultModule.TopLevelDecls.Add(iter); .) - | TraitDecl (. defaultModule.TopLevelDecls.Add(trait); .) - | ClassMemberDecl - } + TopDecls (. // find the default class in the default module, then append membersDefaultClass to its member list DefaultClassDecl defaultClass = null; foreach (TopLevelDecl topleveldecl in defaultModule.TopLevelDecls) { @@ -564,43 +656,71 @@ Dafny } .) EOF . -SubModuleDecl -= (. ClassDecl/*!*/ c; DatatypeDecl/*!*/ dt; TopLevelDecl td; IteratorDecl iter; - Attributes attrs = null; IToken/*!*/ id; - TraitDecl/*!*/ trait; - List namedModuleDefaultClassMembers = new List();; + +TopDecls<. ModuleDefinition module, List membersDefaultClass, bool isTopLevel, bool isAbstract .> += { TopDecl } + . + +DeclModifiers += (. dmod = new DeclModifierData(); .) + { "abstract" (. dmod.IsAbstract = true; CheckAndSetToken(ref dmod.AbstractToken); .) + | "ghost" (. dmod.IsGhost = true; CheckAndSetToken(ref dmod.GhostToken); .) + | "static" (. dmod.IsStatic = true; CheckAndSetToken(ref dmod.StaticToken); .) + | "protected" (. dmod.IsProtected = true; CheckAndSetToken(ref dmod.ProtectedToken); .) + | "extern" (. dmod.IsExtern = true; CheckAndSetToken(ref dmod.ExternToken); .) + [ stringToken (. bool isVerbatimString; + string s = Util.RemoveParsedStringQuotes(t.val, out isVerbatimString); + dmod.ExternName = new StringLiteralExpr(t, s, isVerbatimString); + .) + ] + } + . + +TopDecl<. ModuleDefinition module, List membersDefaultClass, bool isTopLevel, bool isAbstract .> += (. DeclModifierData dmod; ModuleDecl submodule; + ClassDecl/*!*/ c; DatatypeDecl/*!*/ dt; TopLevelDecl td; IteratorDecl iter; + TraitDecl/*!*/ trait; + .) + DeclModifiers + ( SubModuleDecl (. module.TopLevelDecls.Add(submodule); .) + | ClassDecl (. module.TopLevelDecls.Add(c); .) + | DatatypeDecl (. module.TopLevelDecls.Add(dt); .) + | NewtypeDecl (. module.TopLevelDecls.Add(td); .) + | OtherTypeDecl (. module.TopLevelDecls.Add(td); .) + | IteratorDecl (. module.TopLevelDecls.Add(iter); .) + | TraitDecl (. module.TopLevelDecls.Add(trait); .) + | ClassMemberDecl + ) . + +SubModuleDecl += (. Attributes attrs = null; IToken/*!*/ id; + List namedModuleDefaultClassMembers = new List();; List idRefined = null, idPath = null, idAssignment = null; ModuleDefinition module; - ModuleDecl sm; submodule = null; // appease compiler - bool isAbstract = false; + bool isAbstract = dmod.IsAbstract; bool isExclusively = false; bool opened = false; + CheckDeclModifiers(dmod, "Modules", AllowedDeclModifiers.Abstract | AllowedDeclModifiers.Extern); .) - ( [ "abstract" (. isAbstract = true; .) ] - "module" + ( "module" { Attribute } NoUSIdent + (. EncodeExternAsAttribute(dmod, ref attrs, id, /* needAxiom */ false); .) [ "exclusively" "refines" QualifiedModuleName (. isExclusively = true; .) | "refines" QualifiedModuleName (. isExclusively = false; .) ] (. module = new ModuleDefinition(id, id.val, isAbstract, false, isExclusively, idRefined == null ? null : idRefined, parent, attrs, false, this); .) "{" (. module.BodyStartTok = t; .) - { SubModuleDecl (. module.TopLevelDecls.Add(sm); .) - | ClassDecl (. module.TopLevelDecls.Add(c); .) - | TraitDecl (. module.TopLevelDecls.Add(trait); .) - | DatatypeDecl (. module.TopLevelDecls.Add(dt); .) - | NewtypeDecl (. module.TopLevelDecls.Add(td); .) - | OtherTypeDecl (. module.TopLevelDecls.Add(td); .) - | IteratorDecl (. module.TopLevelDecls.Add(iter); .) - | ClassMemberDecl - } - "}" (. module.BodyEndTok = t; + TopDecls + "}" (. module.BodyEndTok = t; module.TopLevelDecls.Add(new DefaultClassDecl(module, namedModuleDefaultClassMembers)); submodule = new LiteralModuleDecl(module, parent); .) | "import" ["opened" (.opened = true;.)] NoUSIdent + (. EncodeExternAsAttribute(dmod, ref attrs, id, /* needAxiom */ false); .) [ "=" QualifiedModuleName (. submodule = new AliasModuleDecl(idPath, id, parent, opened); .) | "as" QualifiedModuleName ["default" QualifiedModuleName ] @@ -629,7 +749,7 @@ QualifiedModuleName<.out List ids.> } . -ClassDecl +ClassDecl = (. Contract.Requires(module != null); Contract.Ensures(Contract.ValueAtReturn(out c) != null); IToken/*!*/ id; @@ -639,18 +759,21 @@ ClassDecl List typeArgs = new List(); List members = new List(); IToken bodyStart; + CheckDeclModifiers(dmodClass, "Classes", AllowedDeclModifiers.Extern); + DeclModifierData dmod; .) SYNC "class" { Attribute } NoUSIdent + (. EncodeExternAsAttribute(dmodClass, ref attrs, id, /* needAxiom */ false); .) [ GenericParameters ] ["extends" Type (. traits.Add(trait); .) {"," Type (. traits.Add(trait); .) } ] "{" (. bodyStart = t; .) - { ClassMemberDecl + { DeclModifiers ClassMemberDecl } "}" (. c = new ClassDecl(id, id.val, module, typeArgs, members, attrs, traits); @@ -659,14 +782,16 @@ ClassDecl .) . - TraitDecl - = (. Contract.Requires(module != null); +TraitDecl + = (. Contract.Requires(module != null); + CheckDeclModifiers(dmodIn, "Traits", AllowedDeclModifiers.None); Contract.Ensures(Contract.ValueAtReturn(out trait) != null); IToken/*!*/ id; Attributes attrs = null; List typeArgs = new List(); //traits should not support type parameters at the moment List members = new List(); IToken bodyStart; + DeclModifierData dmod; .) SYNC "trait" @@ -674,7 +799,7 @@ ClassDecl NoUSIdent [ GenericParameters ] "{" (. bodyStart = t; .) - { ClassMemberDecl + { DeclModifiers ClassMemberDecl } "}" (. trait = new TraitDecl(id, id.val, module, typeArgs, members, attrs); @@ -683,44 +808,33 @@ ClassDecl .) . -ClassMemberDecl<.List mm, bool allowConstructors, bool moduleLevelDecl, bool isWithinAbstractModule.> +ClassMemberDecl<. DeclModifierData dmod, List mm, bool allowConstructors, bool moduleLevelDecl, bool isWithinAbstractModule.> = (. Contract.Requires(cce.NonNullElements(mm)); Method/*!*/ m; Function/*!*/ f; - MemberModifiers mmod = new MemberModifiers(); - IToken staticToken = null, protectedToken = null; .) - { "ghost" (. mmod.IsGhost = true; .) - | "static" (. mmod.IsStatic = true; staticToken = t; .) - | "protected" (. mmod.IsProtected = true; protectedToken = t; .) - } ( (. if (moduleLevelDecl) { SemErr(la, "fields are not allowed to be declared at the module level; instead, wrap the field in a 'class' declaration"); - mmod.IsStatic = false; - mmod.IsProtected = false; + dmod.IsStatic = false; } .) - FieldDecl + FieldDecl | IF(IsFunctionDecl()) - (. if (moduleLevelDecl && staticToken != null) { - errors.Warning(staticToken, "module-level functions are always non-instance, so the 'static' keyword is not allowed here"); - mmod.IsStatic = false; + (. if (moduleLevelDecl && dmod.StaticToken != null) { + errors.Warning(dmod.StaticToken, "module-level functions are always non-instance, so the 'static' keyword is not allowed here"); + dmod.IsStatic = false; } .) - FunctionDecl (. mm.Add(f); .) - | (. if (moduleLevelDecl && staticToken != null) { - errors.Warning(staticToken, "module-level methods are always non-instance, so the 'static' keyword is not allowed here"); - mmod.IsStatic = false; - } - if (protectedToken != null) { - SemErr(protectedToken, "only functions, not methods, can be declared 'protected'"); - mmod.IsProtected = false; + FunctionDecl (. mm.Add(f); .) + | (. if (moduleLevelDecl && dmod.StaticToken != null) { + errors.Warning(dmod.StaticToken, "module-level methods are always non-instance, so the 'static' keyword is not allowed here"); + dmod.IsStatic = false; } .) - MethodDecl (. mm.Add(m); .) + MethodDecl (. mm.Add(m); .) ) . -DatatypeDecl +DatatypeDecl = (. Contract.Requires(module != null); Contract.Ensures(Contract.ValueAtReturn(out dt)!=null); IToken/*!*/ id; @@ -729,6 +843,7 @@ DatatypeDecl List ctors = new List(); IToken bodyStart = Token.NoToken; // dummy assignment bool co = false; + CheckDeclModifiers(dmod, "Datatypes or codatatypes", AllowedDeclModifiers.None); .) SYNC ( "datatype" @@ -766,27 +881,27 @@ DatatypeMemberDecl<.List/*!*/ ctors.> [ FormalsOptionalIds ] (. ctors.Add(new DatatypeCtor(id, id.val, formals, attrs)); .) . -FieldDecl<.MemberModifiers mmod, List/*!*/ mm.> +FieldDecl<.DeclModifierData dmod, List/*!*/ mm.> = (. Contract.Requires(cce.NonNullElements(mm)); Attributes attrs = null; IToken/*!*/ id; Type/*!*/ ty; + CheckDeclModifiers(dmod, "Fields", AllowedDeclModifiers.Ghost); .) SYNC "var" - (. if (mmod.IsStatic) { SemErr(t, "fields cannot be declared 'static'"); } - .) { Attribute } - FIdentType (. mm.Add(new Field(id, id.val, mmod.IsGhost, ty, attrs)); .) - { "," FIdentType (. mm.Add(new Field(id, id.val, mmod.IsGhost, ty, attrs)); .) + FIdentType (. mm.Add(new Field(id, id.val, dmod.IsGhost, ty, attrs)); .) + { "," FIdentType (. mm.Add(new Field(id, id.val, dmod.IsGhost, ty, attrs)); .) } OldSemi . -NewtypeDecl +NewtypeDecl = (. IToken id, bvId; Attributes attrs = null; td = null; Type baseType = null; Expression wh; + CheckDeclModifiers(dmod, "Newtypes", AllowedDeclModifiers.None); .) "newtype" { Attribute } @@ -800,13 +915,14 @@ NewtypeDecl | Type (. td = new NewtypeDecl(theVerifyThisFile ? id : new IncludeToken(id), id.val, module, baseType, attrs); .) ) . -OtherTypeDecl +OtherTypeDecl = (. IToken id; Attributes attrs = null; var eqSupport = TypeParameter.EqualitySupportValue.Unspecified; var typeArgs = new List(); td = null; Type ty; + CheckDeclModifiers(dmod, "Type aliases", AllowedDeclModifiers.None); .) "type" { Attribute } @@ -902,7 +1018,7 @@ TypeIdentOptional +IteratorDecl = (. Contract.Ensures(Contract.ValueAtReturn(out iter) != null); IToken/*!*/ id; Attributes attrs = null; @@ -924,6 +1040,7 @@ IteratorDecl IToken signatureEllipsis = null; IToken bodyStart = Token.NoToken; IToken bodyEnd = Token.NoToken; + CheckDeclModifiers(dmod, "Iterators", AllowedDeclModifiers.None); .) SYNC "iterator" @@ -969,7 +1086,7 @@ GenericParameters<.List/*!*/ typeArgs.> ">" . /*------------------------------------------------------------------------*/ -MethodDecl +MethodDecl = (. Contract.Ensures(Contract.ValueAtReturn(out m) !=null); IToken/*!*/ id = Token.NoToken; bool hasName = false; IToken keywordToken; @@ -991,43 +1108,36 @@ MethodDecl } [ NoUSIdent (. hasName = true; .) ] @@ -1037,12 +1147,13 @@ MethodDecl ] - Formals + Formals [ "returns" (. if (isConstructor) { SemErr(t, "constructors cannot have out-parameters"); } .) - Formals + Formals ] | "..." (. signatureEllipsis = t; .) ) @@ -1059,16 +1170,16 @@ MethodDecl(mod, modAttrs), ens, new Specification(dec, decAttrs), body, attrs, signatureEllipsis); } else if (isIndLemma) { - m = new InductiveLemma(tok, id.val, mmod.IsStatic, typeArgs, ins, outs, + m = new InductiveLemma(tok, id.val, dmod.IsStatic, typeArgs, ins, outs, req, new Specification(mod, modAttrs), ens, new Specification(dec, decAttrs), body, attrs, signatureEllipsis); } else if (isCoLemma) { - m = new CoLemma(tok, id.val, mmod.IsStatic, typeArgs, ins, outs, + m = new CoLemma(tok, id.val, dmod.IsStatic, typeArgs, ins, outs, req, new Specification(mod, modAttrs), ens, new Specification(dec, decAttrs), body, attrs, signatureEllipsis); } else if (isLemma) { - m = new Lemma(tok, id.val, mmod.IsStatic, typeArgs, ins, outs, + m = new Lemma(tok, id.val, dmod.IsStatic, typeArgs, ins, outs, req, new Specification(mod, modAttrs), ens, new Specification(dec, decAttrs), body, attrs, signatureEllipsis); } else { - m = new Method(tok, id.val, mmod.IsStatic, mmod.IsGhost, typeArgs, ins, outs, + m = new Method(tok, id.val, dmod.IsStatic, dmod.IsGhost, typeArgs, ins, outs, req, new Specification(mod, modAttrs), ens, new Specification(dec, decAttrs), body, attrs, signatureEllipsis); } m.BodyStartTok = bodyStart; @@ -1273,7 +1384,7 @@ GenericInstantiation<.List/*!*/ gt.> ">" . /*------------------------------------------------------------------------*/ -FunctionDecl +FunctionDecl = (. Contract.Ensures(Contract.ValueAtReturn(out f)!=null); Attributes attrs = null; IToken/*!*/ id = Token.NoToken; // to please compiler @@ -1296,7 +1407,13 @@ FunctionDecl } NoUSIdent @@ -1312,7 +1429,13 @@ FunctionDecl } NoUSIdent @@ -1327,7 +1450,8 @@ FunctionDecl } NoUSIdent @@ -1341,7 +1465,8 @@ FunctionDecl } NoUSIdent @@ -1358,22 +1483,23 @@ FunctionDecl } [ FunctionBody ] - (. if (!isWithinAbstractModule && DafnyOptions.O.DisallowSoundnessCheating && body == null && ens.Count > 0 && !Attributes.Contains(attrs, "axiom") && !Attributes.Contains(attrs, "imported")) { + (. if (!isWithinAbstractModule && DafnyOptions.O.DisallowSoundnessCheating && body == null && ens.Count > 0 && + !Attributes.Contains(attrs, "axiom") && !Attributes.Contains(attrs, "imported")) { SemErr(t, "a function with an ensures clause must have a body, unless given the :axiom attribute"); } - + EncodeExternAsAttribute(dmod, ref attrs, id, /* needAxiom */ true); IToken tok = theVerifyThisFile ? id : new IncludeToken(id); if (isPredicate) { - f = new Predicate(tok, id.val, mmod.IsStatic, mmod.IsProtected, !isFunctionMethod, typeArgs, formals, + f = new Predicate(tok, id.val, dmod.IsStatic, dmod.IsProtected, !isFunctionMethod, typeArgs, formals, reqs, reads, ens, new Specification(decreases, null), body, Predicate.BodyOriginKind.OriginalOrInherited, attrs, signatureEllipsis); } else if (isIndPredicate) { - f = new InductivePredicate(tok, id.val, mmod.IsStatic, mmod.IsProtected, typeArgs, formals, + f = new InductivePredicate(tok, id.val, dmod.IsStatic, dmod.IsProtected, typeArgs, formals, reqs, reads, ens, body, attrs, signatureEllipsis); } else if (isCoPredicate) { - f = new CoPredicate(tok, id.val, mmod.IsStatic, mmod.IsProtected, typeArgs, formals, + f = new CoPredicate(tok, id.val, dmod.IsStatic, dmod.IsProtected, typeArgs, formals, reqs, reads, ens, body, attrs, signatureEllipsis); } else { - f = new Function(tok, id.val, mmod.IsStatic, mmod.IsProtected, !isFunctionMethod, typeArgs, formals, returnType, + f = new Function(tok, id.val, dmod.IsStatic, dmod.IsProtected, !isFunctionMethod, typeArgs, formals, returnType, reqs, reads, ens, new Specification(decreases, null), body, attrs, signatureEllipsis); } f.BodyStartTok = bodyStart; diff --git a/Source/Dafny/DafnyAst.cs b/Source/Dafny/DafnyAst.cs index 4c1e2bd7..a51e30de 100644 --- a/Source/Dafny/DafnyAst.cs +++ b/Source/Dafny/DafnyAst.cs @@ -1059,7 +1059,7 @@ namespace Microsoft.Dafny { public virtual string FullCompileName { get { if (ResolvedClass != null && !ResolvedClass.Module.IsDefaultModule) { - return ResolvedClass.Module.CompileName + ".@" + CompileName; + return ResolvedClass.Module.CompileName + ".@" + ResolvedClass.CompileName; } else { return CompileName; } @@ -1536,7 +1536,17 @@ namespace Microsoft.Dafny { public virtual string CompileName { get { if (compileName == null) { - compileName = NonglobalVariable.CompilerizeName(Name); + object externValue = ""; + string errorMessage = ""; + bool isExternal = Attributes.ContainsMatchingValue(this.Attributes, "extern", ref externValue, + new Attributes.MatchingValueOption[] { Attributes.MatchingValueOption.String }, + err => errorMessage = err); + if (isExternal) { + compileName = (string)externValue; + } + else { + compileName = NonglobalVariable.CompilerizeName(Name); + } } return compileName; } @@ -1835,10 +1845,19 @@ namespace Microsoft.Dafny { public string CompileName { get { if (compileName == null) { - if (IsBuiltinName) - compileName = Name; - else - compileName = "_" + Height.ToString() + "_" + NonglobalVariable.CompilerizeName(Name); + object externValue = ""; + string errorMessage = ""; + bool isExternal = Attributes.ContainsMatchingValue(this.Attributes, "extern", ref externValue, + new Attributes.MatchingValueOption[] { Attributes.MatchingValueOption.String }, + err => errorMessage = err); + if (isExternal) { + compileName = (string)externValue; + } else { + if (IsBuiltinName) + compileName = Name; + else + compileName = "_" + Height.ToString() + "_" + NonglobalVariable.CompilerizeName(Name); + } } return compileName; } diff --git a/Source/Dafny/Makefile b/Source/Dafny/Makefile index 68ab7a2d..a61539b0 100644 --- a/Source/Dafny/Makefile +++ b/Source/Dafny/Makefile @@ -4,8 +4,8 @@ # from http://boogiepartners.codeplex.com/. Update the FRAME_DIR variable to # point to whatever directory you install that into. # ############################################################################### -COCO_EXE_DIR = ..\..\..\boogie-partners\CocoR\bin -FRAME_DIR = ..\..\..\boogie-partners\CocoR\Modified +COCO_EXE_DIR = ..\..\..\coco +FRAME_DIR = ..\..\..\boogiepartners\CocoR\Modified COCO = $(COCO_EXE_DIR)\Coco.exe # "all" depends on 2 files, really (Parser.cs and Scanner.cs), but they diff --git a/Source/Dafny/Parser.cs b/Source/Dafny/Parser.cs index 922aad75..dc661fc5 100644 --- a/Source/Dafny/Parser.cs +++ b/Source/Dafny/Parser.cs @@ -73,7 +73,7 @@ public class Parser { public const int _star = 57; public const int _notIn = 58; public const int _ellipsis = 59; - public const int maxT = 138; + public const int maxT = 139; const bool _T = true; const bool _x = false; @@ -95,10 +95,113 @@ readonly BuiltIns theBuiltIns; readonly bool theVerifyThisFile; int anonymousIds = 0; -struct MemberModifiers { +/// +/// Holds the modifiers given for a declaration +/// +/// Not all modifiers are applicable to all kinds of declarations. +/// Errors are given when a modify does not apply. +/// We also record the tokens for the specified modifiers so that +/// they can be used in error messages. +/// +struct DeclModifierData { + public bool IsAbstract; + public IToken AbstractToken; public bool IsGhost; + public IToken GhostToken; public bool IsStatic; + public IToken StaticToken; public bool IsProtected; + public IToken ProtectedToken; + public bool IsExtern; + public IToken ExternToken; + public StringLiteralExpr ExternName; + +} + +// Check that token has not been set, then set it. +public void CheckAndSetToken(ref IToken token) +{ + if (token != null) { + SemErr(t, "Duplicate declaration modifier: " + t.val); + } + token = t; +} + +/// +// A flags type used to tell what declaration modifiers are allowed for a declaration. +/// +[Flags] +enum AllowedDeclModifiers { + None = 0, + Abstract = 1, + Ghost = 2, + + // Means ghost not allowed because already implicitly ghost. + AlreadyGhost = 4, + Static = 8, + Protected = 16, + Extern = 32 +}; + +/// +/// Check the declaration modifiers against those that are allowed. +/// +/// The 'allowed' parameter specifies which declaratio modifiers are allowed. +/// The 'declCaption' parameter should be a string describing the kind of declaration. +/// It is used in error messages. +/// Any declaration modifiers that are present but not allowed are cleared. +/// +void CheckDeclModifiers(DeclModifierData dmod, string declCaption, AllowedDeclModifiers allowed) +{ + if (dmod.IsAbstract && ((allowed & AllowedDeclModifiers.Abstract) == 0)) { + SemErr(dmod.AbstractToken, declCaption + " cannot be declared 'abstract'."); + dmod.IsAbstract = false; + } + if (dmod.IsGhost) { + if ((allowed & AllowedDeclModifiers.AlreadyGhost) != 0) { + SemErr(dmod.GhostToken, declCaption + " cannot be declared ghost (they are 'ghost' by default)."); + dmod.IsGhost = false; + } else if ((allowed & AllowedDeclModifiers.Ghost) == 0) { + SemErr(dmod.GhostToken, declCaption + " cannot be declared 'ghost'."); + dmod.IsGhost = false; + } + } + if (dmod.IsStatic && ((allowed & AllowedDeclModifiers.Static) == 0)) { + SemErr(dmod.StaticToken, declCaption + " cannot be declared 'static'."); + dmod.IsStatic = false; + } + if (dmod.IsProtected && ((allowed & AllowedDeclModifiers.Protected) == 0)) { + SemErr(dmod.ProtectedToken, declCaption + " cannot be declared 'protected'."); + dmod.IsProtected = false; + } + if (dmod.IsExtern && ((allowed & AllowedDeclModifiers.Extern) == 0)) { + SemErr(dmod.ExternToken, declCaption + " cannot be declared 'extern'."); + dmod.IsExtern = false; + } +} + +/// +/// Encode an 'extern' declaration modifier as an {:extern name} attribute. +/// +/// We also include an {:axiom} attribute since the specification of an +/// external entity is assumed to hold, but only for methods or functions. +/// +static void EncodeExternAsAttribute(DeclModifierData dmod, ref Attributes attrs, IToken/*!*/ id, bool needAxiom) { + if (dmod.IsExtern) { + StringLiteralExpr name = dmod.ExternName; + if (name == null) { + bool isVerbatimString = false; + name = new StringLiteralExpr(id, id.val, isVerbatimString); + } + var args = new List(); + args.Add(name); + attrs = new Attributes("extern", args, attrs); + + // Also 'extern' implies 'axiom' for methods or functions. + if (needAxiom) { + attrs = new Attributes("axiom", new List(), attrs); + } + } } /// @@ -543,13 +646,10 @@ bool IsType(ref IToken pt) { void Dafny() { - ClassDecl/*!*/ c; DatatypeDecl/*!*/ dt; TopLevelDecl td; IteratorDecl iter; List membersDefaultClass = new List(); - ModuleDecl submodule; // to support multiple files, create a default module only if theModule is null DefaultModuleDecl defaultModule = (DefaultModuleDecl)((LiteralModuleDecl)theModule).ModuleDef; // theModule should be a DefaultModuleDecl (actually, the singular DefaultModuleDecl) - TraitDecl/*!*/ trait; Contract.Assert(defaultModule != null); while (la.kind == 60) { @@ -570,49 +670,7 @@ bool IsType(ref IToken pt) { } } - while (StartOf(1)) { - switch (la.kind) { - case 61: case 62: case 65: { - SubModuleDecl(defaultModule, out submodule); - defaultModule.TopLevelDecls.Add(submodule); - break; - } - case 70: { - ClassDecl(defaultModule, out c); - defaultModule.TopLevelDecls.Add(c); - break; - } - case 76: case 77: { - DatatypeDecl(defaultModule, out dt); - defaultModule.TopLevelDecls.Add(dt); - break; - } - case 79: { - NewtypeDecl(defaultModule, out td); - defaultModule.TopLevelDecls.Add(td); - break; - } - case 80: { - OtherTypeDecl(defaultModule, out td); - defaultModule.TopLevelDecls.Add(td); - break; - } - case 81: { - IteratorDecl(defaultModule, out iter); - defaultModule.TopLevelDecls.Add(iter); - break; - } - case 72: { - TraitDecl(defaultModule, out trait); - defaultModule.TopLevelDecls.Add(trait); - break; - } - case 38: case 39: case 40: case 41: case 42: case 73: case 74: case 75: case 78: case 84: case 85: case 86: case 87: { - ClassMemberDecl(membersDefaultClass, false, !DafnyOptions.O.AllowGlobals, false); - break; - } - } - } + TopDecls(defaultModule, membersDefaultClass, /* isTopLevel */ true, /* isAbstract */ false); DefaultClassDecl defaultClass = null; foreach (TopLevelDecl topleveldecl in defaultModule.TopLevelDecls) { defaultClass = topleveldecl as DefaultClassDecl; @@ -628,33 +686,114 @@ bool IsType(ref IToken pt) { Expect(0); } - void SubModuleDecl(ModuleDefinition parent, out ModuleDecl submodule) { + void TopDecls(ModuleDefinition module, List membersDefaultClass, bool isTopLevel, bool isAbstract ) { + while (StartOf(1)) { + TopDecl(module, membersDefaultClass, isTopLevel, isAbstract); + } + } + + void TopDecl(ModuleDefinition module, List membersDefaultClass, bool isTopLevel, bool isAbstract ) { + DeclModifierData dmod; ModuleDecl submodule; ClassDecl/*!*/ c; DatatypeDecl/*!*/ dt; TopLevelDecl td; IteratorDecl iter; - Attributes attrs = null; IToken/*!*/ id; TraitDecl/*!*/ trait; + + DeclModifiers(out dmod); + switch (la.kind) { + case 66: case 69: { + SubModuleDecl(dmod, module, out submodule); + module.TopLevelDecls.Add(submodule); + break; + } + case 74: { + ClassDecl(dmod, module, out c); + module.TopLevelDecls.Add(c); + break; + } + case 77: case 78: { + DatatypeDecl(dmod, module, out dt); + module.TopLevelDecls.Add(dt); + break; + } + case 80: { + NewtypeDecl(dmod, module, out td); + module.TopLevelDecls.Add(td); + break; + } + case 81: { + OtherTypeDecl(dmod, module, out td); + module.TopLevelDecls.Add(td); + break; + } + case 82: { + IteratorDecl(dmod, module, out iter); + module.TopLevelDecls.Add(iter); + break; + } + case 76: { + TraitDecl(dmod, module, out trait); + module.TopLevelDecls.Add(trait); + break; + } + case 38: case 39: case 40: case 41: case 42: case 79: case 85: case 86: case 87: case 88: { + ClassMemberDecl(dmod, membersDefaultClass, false, !DafnyOptions.O.AllowGlobals, +!isTopLevel && DafnyOptions.O.IronDafny && isAbstract); + break; + } + default: SynErr(140); break; + } + } + + void DeclModifiers(out DeclModifierData dmod) { + dmod = new DeclModifierData(); + while (StartOf(2)) { + if (la.kind == 61) { + Get(); + dmod.IsAbstract = true; CheckAndSetToken(ref dmod.AbstractToken); + } else if (la.kind == 62) { + Get(); + dmod.IsGhost = true; CheckAndSetToken(ref dmod.GhostToken); + } else if (la.kind == 63) { + Get(); + dmod.IsStatic = true; CheckAndSetToken(ref dmod.StaticToken); + } else if (la.kind == 64) { + Get(); + dmod.IsProtected = true; CheckAndSetToken(ref dmod.ProtectedToken); + } else { + Get(); + dmod.IsExtern = true; CheckAndSetToken(ref dmod.ExternToken); + if (la.kind == 20) { + Get(); + bool isVerbatimString; + string s = Util.RemoveParsedStringQuotes(t.val, out isVerbatimString); + dmod.ExternName = new StringLiteralExpr(t, s, isVerbatimString); + + } + } + } + } + + void SubModuleDecl(DeclModifierData dmod, ModuleDefinition parent, out ModuleDecl submodule) { + Attributes attrs = null; IToken/*!*/ id; List namedModuleDefaultClassMembers = new List();; List idRefined = null, idPath = null, idAssignment = null; ModuleDefinition module; - ModuleDecl sm; submodule = null; // appease compiler - bool isAbstract = false; + bool isAbstract = dmod.IsAbstract; bool isExclusively = false; bool opened = false; + CheckDeclModifiers(dmod, "Modules", AllowedDeclModifiers.Abstract | AllowedDeclModifiers.Extern); - if (la.kind == 61 || la.kind == 62) { - if (la.kind == 61) { - Get(); - isAbstract = true; - } - Expect(62); + if (la.kind == 66) { + Get(); while (la.kind == 46) { Attribute(ref attrs); } NoUSIdent(out id); - if (la.kind == 63 || la.kind == 64) { - if (la.kind == 63) { + EncodeExternAsAttribute(dmod, ref attrs, id, /* needAxiom */ false); + if (la.kind == 67 || la.kind == 68) { + if (la.kind == 67) { Get(); - Expect(64); + Expect(68); QualifiedModuleName(out idRefined); isExclusively = true; } else { @@ -666,69 +805,28 @@ bool IsType(ref IToken pt) { module = new ModuleDefinition(id, id.val, isAbstract, false, isExclusively, idRefined == null ? null : idRefined, parent, attrs, false, this); Expect(46); module.BodyStartTok = t; - while (StartOf(1)) { - switch (la.kind) { - case 61: case 62: case 65: { - SubModuleDecl(module, out sm); - module.TopLevelDecls.Add(sm); - break; - } - case 70: { - ClassDecl(module, out c); - module.TopLevelDecls.Add(c); - break; - } - case 72: { - TraitDecl(module, out trait); - module.TopLevelDecls.Add(trait); - break; - } - case 76: case 77: { - DatatypeDecl(module, out dt); - module.TopLevelDecls.Add(dt); - break; - } - case 79: { - NewtypeDecl(module, out td); - module.TopLevelDecls.Add(td); - break; - } - case 80: { - OtherTypeDecl(module, out td); - module.TopLevelDecls.Add(td); - break; - } - case 81: { - IteratorDecl(module, out iter); - module.TopLevelDecls.Add(iter); - break; - } - case 38: case 39: case 40: case 41: case 42: case 73: case 74: case 75: case 78: case 84: case 85: case 86: case 87: { - ClassMemberDecl(namedModuleDefaultClassMembers, false, !DafnyOptions.O.AllowGlobals, DafnyOptions.O.IronDafny && isAbstract); - break; - } - } - } + TopDecls(module, namedModuleDefaultClassMembers, /* isTopLevel */ false, isAbstract); Expect(47); module.BodyEndTok = t; module.TopLevelDecls.Add(new DefaultClassDecl(module, namedModuleDefaultClassMembers)); submodule = new LiteralModuleDecl(module, parent); - } else if (la.kind == 65) { + } else if (la.kind == 69) { Get(); - if (la.kind == 66) { + if (la.kind == 70) { Get(); opened = true; } NoUSIdent(out id); - if (la.kind == 67 || la.kind == 68) { - if (la.kind == 67) { + EncodeExternAsAttribute(dmod, ref attrs, id, /* needAxiom */ false); + if (la.kind == 71 || la.kind == 72) { + if (la.kind == 71) { Get(); QualifiedModuleName(out idPath); submodule = new AliasModuleDecl(idPath, id, parent, opened); } else { Get(); QualifiedModuleName(out idPath); - if (la.kind == 69) { + if (la.kind == 73) { Get(); QualifiedModuleName(out idAssignment); } @@ -736,7 +834,7 @@ bool IsType(ref IToken pt) { } } if (la.kind == 28) { - while (!(la.kind == 0 || la.kind == 28)) {SynErr(139); Get();} + while (!(la.kind == 0 || la.kind == 28)) {SynErr(141); Get();} Get(); errors.Warning(t, "the semi-colon that used to terminate a sub-module declaration has been deprecated; in the new syntax, just leave off the semi-colon"); } @@ -746,10 +844,10 @@ bool IsType(ref IToken pt) { submodule = new AliasModuleDecl(idPath, id, parent, opened); } - } else SynErr(140); + } else SynErr(142); } - void ClassDecl(ModuleDefinition/*!*/ module, out ClassDecl/*!*/ c) { + void ClassDecl(DeclModifierData dmodClass, ModuleDefinition/*!*/ module, out ClassDecl/*!*/ c) { Contract.Requires(module != null); Contract.Ensures(Contract.ValueAtReturn(out c) != null); IToken/*!*/ id; @@ -759,17 +857,20 @@ bool IsType(ref IToken pt) { List typeArgs = new List(); List members = new List(); IToken bodyStart; + CheckDeclModifiers(dmodClass, "Classes", AllowedDeclModifiers.Extern); + DeclModifierData dmod; - while (!(la.kind == 0 || la.kind == 70)) {SynErr(141); Get();} - Expect(70); + while (!(la.kind == 0 || la.kind == 74)) {SynErr(143); Get();} + Expect(74); while (la.kind == 46) { Attribute(ref attrs); } NoUSIdent(out id); + EncodeExternAsAttribute(dmodClass, ref attrs, id, /* needAxiom */ false); if (la.kind == 52) { GenericParameters(typeArgs); } - if (la.kind == 71) { + if (la.kind == 75) { Get(); Type(out trait); traits.Add(trait); @@ -781,8 +882,9 @@ bool IsType(ref IToken pt) { } Expect(46); bodyStart = t; - while (StartOf(2)) { - ClassMemberDecl(members, true, false, false); + while (StartOf(3)) { + DeclModifiers(out dmod); + ClassMemberDecl(dmod, members, true, false, false); } Expect(47); c = new ClassDecl(id, id.val, module, typeArgs, members, attrs, traits); @@ -791,7 +893,7 @@ bool IsType(ref IToken pt) { } - void DatatypeDecl(ModuleDefinition/*!*/ module, out DatatypeDecl/*!*/ dt) { + void DatatypeDecl(DeclModifierData dmod, ModuleDefinition/*!*/ module, out DatatypeDecl/*!*/ dt) { Contract.Requires(module != null); Contract.Ensures(Contract.ValueAtReturn(out dt)!=null); IToken/*!*/ id; @@ -800,14 +902,15 @@ bool IsType(ref IToken pt) { List ctors = new List(); IToken bodyStart = Token.NoToken; // dummy assignment bool co = false; + CheckDeclModifiers(dmod, "Datatypes or codatatypes", AllowedDeclModifiers.None); - while (!(la.kind == 0 || la.kind == 76 || la.kind == 77)) {SynErr(142); Get();} - if (la.kind == 76) { + while (!(la.kind == 0 || la.kind == 77 || la.kind == 78)) {SynErr(144); Get();} + if (la.kind == 77) { Get(); - } else if (la.kind == 77) { + } else if (la.kind == 78) { Get(); co = true; - } else SynErr(143); + } else SynErr(145); while (la.kind == 46) { Attribute(ref attrs); } @@ -815,7 +918,7 @@ bool IsType(ref IToken pt) { if (la.kind == 52) { GenericParameters(typeArgs); } - Expect(67); + Expect(71); bodyStart = t; DatatypeMemberDecl(ctors); while (la.kind == 23) { @@ -823,7 +926,7 @@ bool IsType(ref IToken pt) { DatatypeMemberDecl(ctors); } if (la.kind == 28) { - while (!(la.kind == 0 || la.kind == 28)) {SynErr(144); Get();} + while (!(la.kind == 0 || la.kind == 28)) {SynErr(146); Get();} Get(); errors.Warning(t, "the semi-colon that used to terminate a (co)datatype declaration has been deprecated; in the new syntax, just leave off the semi-colon"); } @@ -837,19 +940,20 @@ bool IsType(ref IToken pt) { } - void NewtypeDecl(ModuleDefinition module, out TopLevelDecl td) { + void NewtypeDecl(DeclModifierData dmod, ModuleDefinition module, out TopLevelDecl td) { IToken id, bvId; Attributes attrs = null; td = null; Type baseType = null; Expression wh; + CheckDeclModifiers(dmod, "Newtypes", AllowedDeclModifiers.None); - Expect(79); + Expect(80); while (la.kind == 46) { Attribute(ref attrs); } NoUSIdent(out id); - Expect(67); + Expect(71); if (IsIdentColonOrBar()) { NoUSIdent(out bvId); if (la.kind == 21) { @@ -860,21 +964,22 @@ bool IsType(ref IToken pt) { Expect(23); Expression(out wh, false, true); td = new NewtypeDecl(theVerifyThisFile ? id : new IncludeToken(id), id.val, module, new BoundVar(bvId, bvId.val, baseType), wh, attrs); - } else if (StartOf(3)) { + } else if (StartOf(4)) { Type(out baseType); td = new NewtypeDecl(theVerifyThisFile ? id : new IncludeToken(id), id.val, module, baseType, attrs); - } else SynErr(145); + } else SynErr(147); } - void OtherTypeDecl(ModuleDefinition module, out TopLevelDecl td) { + void OtherTypeDecl(DeclModifierData dmod, ModuleDefinition module, out TopLevelDecl td) { IToken id; Attributes attrs = null; var eqSupport = TypeParameter.EqualitySupportValue.Unspecified; var typeArgs = new List(); td = null; Type ty; + CheckDeclModifiers(dmod, "Type aliases", AllowedDeclModifiers.None); - Expect(80); + Expect(81); while (la.kind == 46) { Attribute(ref attrs); } @@ -887,28 +992,28 @@ bool IsType(ref IToken pt) { if (la.kind == 52) { GenericParameters(typeArgs); } - } else if (StartOf(4)) { + } else if (StartOf(5)) { if (la.kind == 52) { GenericParameters(typeArgs); } - if (la.kind == 67) { + if (la.kind == 71) { Get(); Type(out ty); td = new TypeSynonymDecl(id, id.val, typeArgs, module, ty, attrs); } - } else SynErr(146); + } else SynErr(148); if (td == null) { td = new OpaqueTypeDecl(id, id.val, module, eqSupport, typeArgs, attrs); } if (la.kind == 28) { - while (!(la.kind == 0 || la.kind == 28)) {SynErr(147); Get();} + while (!(la.kind == 0 || la.kind == 28)) {SynErr(149); Get();} Get(); errors.Warning(t, "the semi-colon that used to terminate an opaque-type declaration has been deprecated; in the new syntax, just leave off the semi-colon"); } } - void IteratorDecl(ModuleDefinition module, out IteratorDecl/*!*/ iter) { + void IteratorDecl(DeclModifierData dmod, ModuleDefinition module, out IteratorDecl/*!*/ iter) { Contract.Ensures(Contract.ValueAtReturn(out iter) != null); IToken/*!*/ id; Attributes attrs = null; @@ -930,9 +1035,10 @@ bool IsType(ref IToken pt) { IToken signatureEllipsis = null; IToken bodyStart = Token.NoToken; IToken bodyEnd = Token.NoToken; + CheckDeclModifiers(dmod, "Iterators", AllowedDeclModifiers.None); - while (!(la.kind == 0 || la.kind == 81)) {SynErr(148); Get();} - Expect(81); + while (!(la.kind == 0 || la.kind == 82)) {SynErr(150); Get();} + Expect(82); while (la.kind == 46) { Attribute(ref attrs); } @@ -942,8 +1048,8 @@ bool IsType(ref IToken pt) { GenericParameters(typeArgs); } Formals(true, true, ins); - if (la.kind == 82 || la.kind == 83) { - if (la.kind == 82) { + if (la.kind == 83 || la.kind == 84) { + if (la.kind == 83) { Get(); } else { Get(); @@ -954,8 +1060,8 @@ bool IsType(ref IToken pt) { } else if (la.kind == 59) { Get(); signatureEllipsis = t; - } else SynErr(149); - while (StartOf(5)) { + } else SynErr(151); + while (StartOf(6)) { IteratorSpec(reads, mod, decreases, req, ens, yieldReq, yieldEns, ref readsAttrs, ref modAttrs, ref decrAttrs); } if (la.kind == 46) { @@ -972,17 +1078,19 @@ bool IsType(ref IToken pt) { } - void TraitDecl(ModuleDefinition/*!*/ module, out TraitDecl/*!*/ trait) { - Contract.Requires(module != null); + void TraitDecl(DeclModifierData dmodIn, ModuleDefinition/*!*/ module, out TraitDecl/*!*/ trait) { + Contract.Requires(module != null); + CheckDeclModifiers(dmodIn, "Traits", AllowedDeclModifiers.None); Contract.Ensures(Contract.ValueAtReturn(out trait) != null); IToken/*!*/ id; Attributes attrs = null; List typeArgs = new List(); //traits should not support type parameters at the moment List members = new List(); IToken bodyStart; + DeclModifierData dmod; - while (!(la.kind == 0 || la.kind == 72)) {SynErr(150); Get();} - Expect(72); + while (!(la.kind == 0 || la.kind == 76)) {SynErr(152); Get();} + Expect(76); while (la.kind == 46) { Attribute(ref attrs); } @@ -992,8 +1100,9 @@ bool IsType(ref IToken pt) { } Expect(46); bodyStart = t; - while (StartOf(2)) { - ClassMemberDecl(members, true, false, false); + while (StartOf(3)) { + DeclModifiers(out dmod); + ClassMemberDecl(dmod, members, true, false, false); } Expect(47); trait = new TraitDecl(id, id.val, module, typeArgs, members, attrs); @@ -1002,54 +1111,35 @@ bool IsType(ref IToken pt) { } - void ClassMemberDecl(List mm, bool allowConstructors, bool moduleLevelDecl, bool isWithinAbstractModule) { + void ClassMemberDecl(DeclModifierData dmod, List mm, bool allowConstructors, bool moduleLevelDecl, bool isWithinAbstractModule) { Contract.Requires(cce.NonNullElements(mm)); Method/*!*/ m; Function/*!*/ f; - MemberModifiers mmod = new MemberModifiers(); - IToken staticToken = null, protectedToken = null; - while (la.kind == 73 || la.kind == 74 || la.kind == 75) { - if (la.kind == 73) { - Get(); - mmod.IsGhost = true; - } else if (la.kind == 74) { - Get(); - mmod.IsStatic = true; staticToken = t; - } else { - Get(); - mmod.IsProtected = true; protectedToken = t; - } - } - if (la.kind == 78) { + if (la.kind == 79) { if (moduleLevelDecl) { SemErr(la, "fields are not allowed to be declared at the module level; instead, wrap the field in a 'class' declaration"); - mmod.IsStatic = false; - mmod.IsProtected = false; + dmod.IsStatic = false; } - FieldDecl(mmod, mm); + FieldDecl(dmod, mm); } else if (IsFunctionDecl()) { - if (moduleLevelDecl && staticToken != null) { - errors.Warning(staticToken, "module-level functions are always non-instance, so the 'static' keyword is not allowed here"); - mmod.IsStatic = false; + if (moduleLevelDecl && dmod.StaticToken != null) { + errors.Warning(dmod.StaticToken, "module-level functions are always non-instance, so the 'static' keyword is not allowed here"); + dmod.IsStatic = false; } - FunctionDecl(mmod, isWithinAbstractModule, out f); + FunctionDecl(dmod, isWithinAbstractModule, out f); mm.Add(f); - } else if (StartOf(6)) { - if (moduleLevelDecl && staticToken != null) { - errors.Warning(staticToken, "module-level methods are always non-instance, so the 'static' keyword is not allowed here"); - mmod.IsStatic = false; - } - if (protectedToken != null) { - SemErr(protectedToken, "only functions, not methods, can be declared 'protected'"); - mmod.IsProtected = false; + } else if (StartOf(7)) { + if (moduleLevelDecl && dmod.StaticToken != null) { + errors.Warning(dmod.StaticToken, "module-level methods are always non-instance, so the 'static' keyword is not allowed here"); + dmod.IsStatic = false; } - MethodDecl(mmod, allowConstructors, isWithinAbstractModule, out m); + MethodDecl(dmod, allowConstructors, isWithinAbstractModule, out m); mm.Add(m); - } else SynErr(151); + } else SynErr(153); } void Attribute(ref Attributes attrs) { @@ -1060,7 +1150,7 @@ bool IsType(ref IToken pt) { Expect(21); NoUSIdent(out x); name = x.val; - if (StartOf(7)) { + if (StartOf(8)) { Expressions(args); } Expect(47); @@ -1129,29 +1219,28 @@ bool IsType(ref IToken pt) { TypeAndToken(out tok, out ty); } - void FieldDecl(MemberModifiers mmod, List/*!*/ mm) { + void FieldDecl(DeclModifierData dmod, List/*!*/ mm) { Contract.Requires(cce.NonNullElements(mm)); Attributes attrs = null; IToken/*!*/ id; Type/*!*/ ty; + CheckDeclModifiers(dmod, "Fields", AllowedDeclModifiers.Ghost); - while (!(la.kind == 0 || la.kind == 78)) {SynErr(152); Get();} - Expect(78); - if (mmod.IsStatic) { SemErr(t, "fields cannot be declared 'static'"); } - + while (!(la.kind == 0 || la.kind == 79)) {SynErr(154); Get();} + Expect(79); while (la.kind == 46) { Attribute(ref attrs); } FIdentType(out id, out ty); - mm.Add(new Field(id, id.val, mmod.IsGhost, ty, attrs)); + mm.Add(new Field(id, id.val, dmod.IsGhost, ty, attrs)); while (la.kind == 22) { Get(); FIdentType(out id, out ty); - mm.Add(new Field(id, id.val, mmod.IsGhost, ty, attrs)); + mm.Add(new Field(id, id.val, dmod.IsGhost, ty, attrs)); } OldSemi(); } - void FunctionDecl(MemberModifiers mmod, bool isWithinAbstractModule, out Function/*!*/ f) { + void FunctionDecl(DeclModifierData dmod, bool isWithinAbstractModule, out Function/*!*/ f) { Contract.Ensures(Contract.ValueAtReturn(out f)!=null); Attributes attrs = null; IToken/*!*/ id = Token.NoToken; // to please compiler @@ -1172,11 +1261,17 @@ bool IsType(ref IToken pt) { if (la.kind == 38) { Get(); - if (la.kind == 84) { + if (la.kind == 85) { Get(); isFunctionMethod = true; } - if (mmod.IsGhost) { SemErr(t, "functions cannot be declared 'ghost' (they are ghost by default)"); } + AllowedDeclModifiers allowed = AllowedDeclModifiers.AlreadyGhost | AllowedDeclModifiers.Static | AllowedDeclModifiers.Protected; + string caption = "Functions"; + if (isFunctionMethod) { + allowed |= AllowedDeclModifiers.Extern; + caption = "Function methods"; + } + CheckDeclModifiers(dmod, caption, allowed); while (la.kind == 46) { Attribute(ref attrs); @@ -1192,21 +1287,27 @@ bool IsType(ref IToken pt) { } else if (la.kind == 59) { Get(); signatureEllipsis = t; - } else SynErr(153); + } else SynErr(155); } else if (la.kind == 39) { Get(); isPredicate = true; - if (la.kind == 84) { + if (la.kind == 85) { Get(); isFunctionMethod = true; } - if (mmod.IsGhost) { SemErr(t, "predicates cannot be declared 'ghost' (they are ghost by default)"); } + AllowedDeclModifiers allowed = AllowedDeclModifiers.AlreadyGhost | AllowedDeclModifiers.Static | AllowedDeclModifiers.Protected; + string caption = "Predicates"; + if (isFunctionMethod) { + allowed |= AllowedDeclModifiers.Extern; + caption = "Predicate methods"; + } + CheckDeclModifiers(dmod, caption, allowed); while (la.kind == 46) { Attribute(ref attrs); } NoUSIdent(out id); - if (StartOf(8)) { + if (StartOf(9)) { if (la.kind == 52) { GenericParameters(typeArgs); } @@ -1223,12 +1324,13 @@ bool IsType(ref IToken pt) { } else if (la.kind == 59) { Get(); signatureEllipsis = t; - } else SynErr(154); + } else SynErr(156); } else if (la.kind == 40) { Get(); Expect(39); isIndPredicate = true; - if (mmod.IsGhost) { SemErr(t, "inductive predicates cannot be declared 'ghost' (they are ghost by default)"); } + CheckDeclModifiers(dmod, "Inductive predicates", + AllowedDeclModifiers.AlreadyGhost | AllowedDeclModifiers.Static | AllowedDeclModifiers.Protected); while (la.kind == 46) { Attribute(ref attrs); @@ -1246,11 +1348,12 @@ bool IsType(ref IToken pt) { } else if (la.kind == 59) { Get(); signatureEllipsis = t; - } else SynErr(155); + } else SynErr(157); } else if (la.kind == 42) { Get(); isCoPredicate = true; - if (mmod.IsGhost) { SemErr(t, "copredicates cannot be declared 'ghost' (they are ghost by default)"); } + CheckDeclModifiers(dmod, "Copredicates", + AllowedDeclModifiers.AlreadyGhost | AllowedDeclModifiers.Static | AllowedDeclModifiers.Protected); while (la.kind == 46) { Attribute(ref attrs); @@ -1268,31 +1371,32 @@ bool IsType(ref IToken pt) { } else if (la.kind == 59) { Get(); signatureEllipsis = t; - } else SynErr(156); - } else SynErr(157); + } else SynErr(158); + } else SynErr(159); decreases = isIndPredicate || isCoPredicate ? null : new List(); - while (StartOf(9)) { + while (StartOf(10)) { FunctionSpec(reqs, reads, ens, decreases); } if (la.kind == 46) { FunctionBody(out body, out bodyStart, out bodyEnd); } - if (!isWithinAbstractModule && DafnyOptions.O.DisallowSoundnessCheating && body == null && ens.Count > 0 && !Attributes.Contains(attrs, "axiom") && !Attributes.Contains(attrs, "imported")) { + if (!isWithinAbstractModule && DafnyOptions.O.DisallowSoundnessCheating && body == null && ens.Count > 0 && + !Attributes.Contains(attrs, "axiom") && !Attributes.Contains(attrs, "imported")) { SemErr(t, "a function with an ensures clause must have a body, unless given the :axiom attribute"); } - + EncodeExternAsAttribute(dmod, ref attrs, id, /* needAxiom */ true); IToken tok = theVerifyThisFile ? id : new IncludeToken(id); if (isPredicate) { - f = new Predicate(tok, id.val, mmod.IsStatic, mmod.IsProtected, !isFunctionMethod, typeArgs, formals, + f = new Predicate(tok, id.val, dmod.IsStatic, dmod.IsProtected, !isFunctionMethod, typeArgs, formals, reqs, reads, ens, new Specification(decreases, null), body, Predicate.BodyOriginKind.OriginalOrInherited, attrs, signatureEllipsis); } else if (isIndPredicate) { - f = new InductivePredicate(tok, id.val, mmod.IsStatic, mmod.IsProtected, typeArgs, formals, + f = new InductivePredicate(tok, id.val, dmod.IsStatic, dmod.IsProtected, typeArgs, formals, reqs, reads, ens, body, attrs, signatureEllipsis); } else if (isCoPredicate) { - f = new CoPredicate(tok, id.val, mmod.IsStatic, mmod.IsProtected, typeArgs, formals, + f = new CoPredicate(tok, id.val, dmod.IsStatic, dmod.IsProtected, typeArgs, formals, reqs, reads, ens, body, attrs, signatureEllipsis); } else { - f = new Function(tok, id.val, mmod.IsStatic, mmod.IsProtected, !isFunctionMethod, typeArgs, formals, returnType, + f = new Function(tok, id.val, dmod.IsStatic, dmod.IsProtected, !isFunctionMethod, typeArgs, formals, returnType, reqs, reads, ens, new Specification(decreases, null), body, attrs, signatureEllipsis); } f.BodyStartTok = bodyStart; @@ -1305,7 +1409,7 @@ bool IsType(ref IToken pt) { } - void MethodDecl(MemberModifiers mmod, bool allowConstructor, bool isWithinAbstractModule, out Method/*!*/ m) { + void MethodDecl(DeclModifierData dmod, bool allowConstructor, bool isWithinAbstractModule, out Method/*!*/ m) { Contract.Ensures(Contract.ValueAtReturn(out m) !=null); IToken/*!*/ id = Token.NoToken; bool hasName = false; IToken keywordToken; @@ -1327,26 +1431,37 @@ bool IsType(ref IToken pt) { IToken signatureEllipsis = null; IToken bodyStart = Token.NoToken; IToken bodyEnd = Token.NoToken; + AllowedDeclModifiers allowed = AllowedDeclModifiers.None; + string caption = ""; - while (!(StartOf(10))) {SynErr(158); Get();} + while (!(StartOf(11))) {SynErr(160); Get();} switch (la.kind) { - case 84: { + case 85: { Get(); + caption = "Methods"; + allowed = AllowedDeclModifiers.Ghost | AllowedDeclModifiers.Static + | AllowedDeclModifiers.Extern; break; } case 41: { Get(); - isLemma = true; + isLemma = true; caption = "Lemmas"; + allowed = AllowedDeclModifiers.AlreadyGhost | AllowedDeclModifiers.Static + | AllowedDeclModifiers.Protected; break; } - case 85: { + case 86: { Get(); - isCoLemma = true; + isCoLemma = true; caption = "Colemmas"; + allowed = AllowedDeclModifiers.AlreadyGhost | AllowedDeclModifiers.Static + | AllowedDeclModifiers.Protected; break; } - case 86: { + case 87: { Get(); - isCoLemma = true; + isCoLemma = true; caption = "Comethods"; + allowed = AllowedDeclModifiers.AlreadyGhost | AllowedDeclModifiers.Static + | AllowedDeclModifiers.Protected; errors.Warning(t, "the 'comethod' keyword has been deprecated; it has been renamed to 'colemma'"); break; @@ -1354,43 +1469,26 @@ bool IsType(ref IToken pt) { case 40: { Get(); Expect(41); - isIndLemma = true; + isIndLemma = true; caption = "Inductive lemmas"; + allowed = AllowedDeclModifiers.AlreadyGhost | AllowedDeclModifiers.Static; break; } - case 87: { + case 88: { Get(); if (allowConstructor) { isConstructor = true; } else { SemErr(t, "constructors are allowed only in classes"); - } + } + caption = "Constructors"; + allowed = AllowedDeclModifiers.None; break; } - default: SynErr(159); break; + default: SynErr(161); break; } keywordToken = t; - if (isLemma) { - if (mmod.IsGhost) { - SemErr(t, "lemmas cannot be declared 'ghost' (they are automatically 'ghost')"); - } - } else if (isConstructor) { - if (mmod.IsGhost) { - SemErr(t, "constructors cannot be declared 'ghost'"); - } - if (mmod.IsStatic) { - SemErr(t, "constructors cannot be declared 'static'"); - } - } else if (isIndLemma) { - if (mmod.IsGhost) { - SemErr(t, "inductive lemmas cannot be declared 'ghost' (they are automatically 'ghost')"); - } - } else if (isCoLemma) { - if (mmod.IsGhost) { - SemErr(t, "colemmas cannot be declared 'ghost' (they are automatically 'ghost')"); - } - } - + CheckDeclModifiers(dmod, caption, allowed); while (la.kind == 46) { Attribute(ref attrs); } @@ -1404,22 +1502,23 @@ bool IsType(ref IToken pt) { SemErr(la, "a method must be given a name (expecting identifier)"); } } + EncodeExternAsAttribute(dmod, ref attrs, id, /* needAxiom */ true); if (la.kind == 50 || la.kind == 52) { if (la.kind == 52) { GenericParameters(typeArgs); } - Formals(true, !mmod.IsGhost, ins); - if (la.kind == 83) { + Formals(true, !dmod.IsGhost, ins); + if (la.kind == 84) { Get(); if (isConstructor) { SemErr(t, "constructors cannot have out-parameters"); } - Formals(false, !mmod.IsGhost, outs); + Formals(false, !dmod.IsGhost, outs); } } else if (la.kind == 59) { Get(); signatureEllipsis = t; - } else SynErr(160); - while (StartOf(11)) { + } else SynErr(162); + while (StartOf(12)) { MethodSpec(req, mod, ens, dec, ref decAttrs, ref modAttrs); } if (la.kind == 46) { @@ -1434,16 +1533,16 @@ bool IsType(ref IToken pt) { m = new Constructor(tok, hasName ? id.val : "_ctor", typeArgs, ins, req, new Specification(mod, modAttrs), ens, new Specification(dec, decAttrs), body, attrs, signatureEllipsis); } else if (isIndLemma) { - m = new InductiveLemma(tok, id.val, mmod.IsStatic, typeArgs, ins, outs, + m = new InductiveLemma(tok, id.val, dmod.IsStatic, typeArgs, ins, outs, req, new Specification(mod, modAttrs), ens, new Specification(dec, decAttrs), body, attrs, signatureEllipsis); } else if (isCoLemma) { - m = new CoLemma(tok, id.val, mmod.IsStatic, typeArgs, ins, outs, + m = new CoLemma(tok, id.val, dmod.IsStatic, typeArgs, ins, outs, req, new Specification(mod, modAttrs), ens, new Specification(dec, decAttrs), body, attrs, signatureEllipsis); } else if (isLemma) { - m = new Lemma(tok, id.val, mmod.IsStatic, typeArgs, ins, outs, + m = new Lemma(tok, id.val, dmod.IsStatic, typeArgs, ins, outs, req, new Specification(mod, modAttrs), ens, new Specification(dec, decAttrs), body, attrs, signatureEllipsis); } else { - m = new Method(tok, id.val, mmod.IsStatic, mmod.IsGhost, typeArgs, ins, outs, + m = new Method(tok, id.val, dmod.IsStatic, dmod.IsGhost, typeArgs, ins, outs, req, new Specification(mod, modAttrs), ens, new Specification(dec, decAttrs), body, attrs, signatureEllipsis); } m.BodyStartTok = bodyStart; @@ -1470,7 +1569,7 @@ bool IsType(ref IToken pt) { void FormalsOptionalIds(List/*!*/ formals) { Contract.Requires(cce.NonNullElements(formals)); IToken/*!*/ id; Type/*!*/ ty; string/*!*/ name; bool isGhost; Expect(50); - if (StartOf(12)) { + if (StartOf(13)) { TypeIdentOptional(out id, out name, out ty, out isGhost); formals.Add(new Formal(id, name, ty, true, isGhost)); while (la.kind == 22) { @@ -1491,14 +1590,14 @@ bool IsType(ref IToken pt) { } else if (la.kind == 2) { Get(); id = t; - } else SynErr(161); + } else SynErr(163); Expect(21); Type(out ty); } void OldSemi() { if (la.kind == 28) { - while (!(la.kind == 0 || la.kind == 28)) {SynErr(162); Get();} + while (!(la.kind == 0 || la.kind == 28)) {SynErr(164); Get();} Get(); } } @@ -1521,7 +1620,7 @@ bool IsType(ref IToken pt) { Contract.Ensures(Contract.ValueAtReturn(out id)!=null); Contract.Ensures(Contract.ValueAtReturn(out ty)!=null); isGhost = false; - if (la.kind == 73) { + if (la.kind == 62) { Get(); if (allowGhostKeyword) { isGhost = true; } else { SemErr(t, "formal cannot be declared 'ghost' in this context"); } } @@ -1573,11 +1672,11 @@ bool IsType(ref IToken pt) { Contract.Ensures(Contract.ValueAtReturn(out ty)!=null); Contract.Ensures(Contract.ValueAtReturn(out identName)!=null); string name = null; id = Token.NoToken; ty = new BoolType()/*dummy*/; isGhost = false; - if (la.kind == 73) { + if (la.kind == 62) { Get(); isGhost = true; } - if (StartOf(3)) { + if (StartOf(4)) { TypeAndToken(out id, out ty); if (la.kind == 21) { Get(); @@ -1595,7 +1694,7 @@ bool IsType(ref IToken pt) { id = t; name = id.val; Expect(21); Type(out ty); - } else SynErr(163); + } else SynErr(165); if (name != null) { identName = name; } else { @@ -1746,7 +1845,7 @@ bool IsType(ref IToken pt) { case 50: { Get(); tok = t; tupleArgTypes = new List(); - if (StartOf(3)) { + if (StartOf(4)) { Type(out ty); tupleArgTypes.Add(ty); while (la.kind == 22) { @@ -1783,7 +1882,7 @@ bool IsType(ref IToken pt) { ty = new UserDefinedType(e.tok, e); break; } - default: SynErr(164); break; + default: SynErr(166); break; } if (la.kind == 30) { Type t2; @@ -1804,7 +1903,7 @@ bool IsType(ref IToken pt) { void Formals(bool incoming, bool allowGhostKeyword, List formals) { Contract.Requires(cce.NonNullElements(formals)); IToken id; Type ty; bool isGhost; Expect(50); - if (la.kind == 1 || la.kind == 73) { + if (la.kind == 1 || la.kind == 62) { GIdentType(allowGhostKeyword, out id, out ty, out isGhost); formals.Add(new Formal(id, id.val, ty, incoming, isGhost)); while (la.kind == 22) { @@ -1822,7 +1921,7 @@ List/*!*/ yieldReq, List/*!* ref Attributes readsAttrs, ref Attributes modAttrs, ref Attributes decrAttrs) { Expression/*!*/ e; FrameExpression/*!*/ fe; bool isFree = false; bool isYield = false; Attributes ensAttrs = null; - while (!(StartOf(13))) {SynErr(165); Get();} + while (!(StartOf(14))) {SynErr(167); Get();} if (la.kind == 44) { Get(); while (IsAttribute()) { @@ -1849,14 +1948,14 @@ ref Attributes readsAttrs, ref Attributes modAttrs, ref Attributes decrAttrs) { mod.Add(fe); } OldSemi(); - } else if (StartOf(14)) { - if (la.kind == 88) { + } else if (StartOf(15)) { + if (la.kind == 89) { Get(); isFree = true; errors.Warning(t, "the 'free' keyword is soon to be deprecated"); } - if (la.kind == 90) { + if (la.kind == 91) { Get(); isYield = true; } @@ -1870,7 +1969,7 @@ ref Attributes readsAttrs, ref Attributes modAttrs, ref Attributes decrAttrs) { req.Add(new MaybeFreeExpression(e, isFree)); } - } else if (la.kind == 89) { + } else if (la.kind == 90) { Get(); while (IsAttribute()) { Attribute(ref ensAttrs); @@ -1883,7 +1982,7 @@ ref Attributes readsAttrs, ref Attributes modAttrs, ref Attributes decrAttrs) { ens.Add(new MaybeFreeExpression(e, isFree, ensAttrs)); } - } else SynErr(166); + } else SynErr(168); } else if (la.kind == 36) { Get(); while (IsAttribute()) { @@ -1891,7 +1990,7 @@ ref Attributes readsAttrs, ref Attributes modAttrs, ref Attributes decrAttrs) { } DecreasesList(decreases, false, false); OldSemi(); - } else SynErr(167); + } else SynErr(169); } void BlockStmt(out BlockStmt/*!*/ block, out IToken bodyStart, out IToken bodyEnd) { @@ -1900,7 +1999,7 @@ ref Attributes readsAttrs, ref Attributes modAttrs, ref Attributes decrAttrs) { Expect(46); bodyStart = t; - while (StartOf(15)) { + while (StartOf(16)) { Stmt(body); } Expect(47); @@ -1913,7 +2012,7 @@ List/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo Contract.Requires(cce.NonNullElements(req)); Contract.Requires(cce.NonNullElements(mod)); Contract.Requires(cce.NonNullElements(ens)); Contract.Requires(cce.NonNullElements(decreases)); Expression/*!*/ e; FrameExpression/*!*/ fe; bool isFree = false; Attributes ensAttrs = null; - while (!(StartOf(16))) {SynErr(168); Get();} + while (!(StartOf(17))) {SynErr(170); Get();} if (la.kind == 43) { Get(); while (IsAttribute()) { @@ -1927,8 +2026,8 @@ List/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo mod.Add(fe); } OldSemi(); - } else if (la.kind == 45 || la.kind == 88 || la.kind == 89) { - if (la.kind == 88) { + } else if (la.kind == 45 || la.kind == 89 || la.kind == 90) { + if (la.kind == 89) { Get(); isFree = true; errors.Warning(t, "the 'free' keyword is soon to be deprecated"); @@ -1939,7 +2038,7 @@ List/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo Expression(out e, false, false); OldSemi(); req.Add(new MaybeFreeExpression(e, isFree)); - } else if (la.kind == 89) { + } else if (la.kind == 90) { Get(); while (IsAttribute()) { Attribute(ref ensAttrs); @@ -1947,7 +2046,7 @@ List/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo Expression(out e, false, false); OldSemi(); ens.Add(new MaybeFreeExpression(e, isFree, ensAttrs)); - } else SynErr(169); + } else SynErr(171); } else if (la.kind == 36) { Get(); while (IsAttribute()) { @@ -1955,7 +2054,7 @@ List/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo } DecreasesList(decreases, true, false); OldSemi(); - } else SynErr(170); + } else SynErr(172); } void FrameExpression(out FrameExpression fe, bool allowSemi, bool allowLambda) { @@ -1965,21 +2064,21 @@ List/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo string fieldName = null; IToken feTok = null; fe = null; - if (StartOf(7)) { + if (StartOf(8)) { Expression(out e, allowSemi, allowLambda); feTok = e.tok; - if (la.kind == 91) { + if (la.kind == 92) { Get(); Ident(out id); fieldName = id.val; feTok = id; } fe = new FrameExpression(feTok, e, fieldName); - } else if (la.kind == 91) { + } else if (la.kind == 92) { Get(); Ident(out id); fieldName = id.val; fe = new FrameExpression(id, new ImplicitThisExpr(id), fieldName); - } else SynErr(171); + } else SynErr(173); } void DecreasesList(List decreases, bool allowWildcard, bool allowLambda) { @@ -2034,7 +2133,7 @@ List/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo Contract.Requires(cce.NonNullElements(reads)); Contract.Requires(decreases == null || cce.NonNullElements(decreases)); Expression/*!*/ e; FrameExpression/*!*/ fe; - while (!(StartOf(17))) {SynErr(172); Get();} + while (!(StartOf(18))) {SynErr(174); Get();} if (la.kind == 45) { Get(); Expression(out e, false, false); @@ -2050,7 +2149,7 @@ List/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo reads.Add(fe); } OldSemi(); - } else if (la.kind == 89) { + } else if (la.kind == 90) { Get(); Expression(out e, false, false); OldSemi(); @@ -2064,7 +2163,7 @@ List/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo DecreasesList(decreases, false, false); OldSemi(); - } else SynErr(173); + } else SynErr(175); } void FunctionBody(out Expression/*!*/ e, out IToken bodyStart, out IToken bodyEnd) { @@ -2081,9 +2180,9 @@ List/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo if (la.kind == 57) { Get(); fe = new FrameExpression(t, new WildcardExpr(t), null); - } else if (StartOf(18)) { + } else if (StartOf(19)) { FrameExpression(out fe, allowSemi, false); - } else SynErr(174); + } else SynErr(176); } void PossiblyWildExpression(out Expression e, bool allowLambda) { @@ -2092,9 +2191,9 @@ List/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo if (la.kind == 57) { Get(); e = new WildcardExpr(t); - } else if (StartOf(7)) { + } else if (StartOf(8)) { Expression(out e, false, allowLambda); - } else SynErr(175); + } else SynErr(177); } void Stmt(List/*!*/ ss) { @@ -2111,14 +2210,14 @@ List/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo IToken bodyStart, bodyEnd; int breakCount; - while (!(StartOf(19))) {SynErr(176); Get();} + while (!(StartOf(20))) {SynErr(178); Get();} switch (la.kind) { case 46: { BlockStmt(out bs, out bodyStart, out bodyEnd); s = bs; break; } - case 101: { + case 102: { AssertStmt(out s); break; } @@ -2126,31 +2225,31 @@ List/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo AssumeStmt(out s); break; } - case 102: { + case 103: { PrintStmt(out s); break; } - case 1: case 2: case 3: case 4: case 8: case 10: case 19: case 20: case 23: case 50: case 131: case 132: case 133: case 134: case 135: case 136: { + case 1: case 2: case 3: case 4: case 8: case 10: case 19: case 20: case 23: case 50: case 132: case 133: case 134: case 135: case 136: case 137: { UpdateStmt(out s); break; } - case 73: case 78: { + case 62: case 79: { VarDeclStatement(out s); break; } - case 98: { + case 99: { IfStmt(out s); break; } - case 99: { + case 100: { WhileStmt(out s); break; } - case 100: { + case 101: { MatchStmt(out s); break; } - case 103: case 104: { + case 104: case 105: { ForallStmt(out s); break; } @@ -2158,11 +2257,11 @@ List/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo CalcStmt(out s); break; } - case 105: { + case 106: { ModifyStmt(out s); break; } - case 92: { + case 93: { Get(); x = t; NoUSIdent(out id); @@ -2171,24 +2270,24 @@ List/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo s.Labels = new LList