From 1763ad8e4d6b631fe966b394ae2dbafa7d803627 Mon Sep 17 00:00:00 2001 From: Clément Pit--Claudel Date: Thu, 23 Jul 2015 10:26:47 -0700 Subject: Fix: Visual studio did not show warnings. To check if the fix works, try declaring a static top level function. Initial work on this patch by Rustan --- Source/DafnyExtension/ResolverTagger.cs | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) (limited to 'Source/DafnyExtension/ResolverTagger.cs') diff --git a/Source/DafnyExtension/ResolverTagger.cs b/Source/DafnyExtension/ResolverTagger.cs index 1fdd3827..4237041f 100644 --- a/Source/DafnyExtension/ResolverTagger.cs +++ b/Source/DafnyExtension/ResolverTagger.cs @@ -68,26 +68,27 @@ namespace DafnyLanguage { Error = error; } - - private static string ConvertToErrorType(DafnyError err) - { - string ty; // the COLORs below indicate what I see on my machine - switch (err.Category) - { - default: // unexpected category + + private static string ConvertToErrorType(DafnyError err) { + // the COLORs below indicate what I see on my machine + switch (err.Category) { + case ErrorCategory.ProcessError: case ErrorCategory.ParseError: case ErrorCategory.ParseWarning: - ty = "syntax error"; break; // COLOR: red + return "syntax error"; // COLOR: red case ErrorCategory.ResolveError: - ty = "compiler error"; break; // COLOR: blue + return "compiler error"; // COLOR: blue + case ErrorCategory.ResolveWarning: + return "compiler warning"; // COLOR: blue + case ErrorCategory.InternalError: case ErrorCategory.VerificationError: - ty = "error"; break; // COLOR: red + return "error"; // COLOR: red case ErrorCategory.AuxInformation: - ty = "other error"; break; // COLOR: purple red - case ErrorCategory.InternalError: - ty = "error"; break; // COLOR: red + return "other error"; // COLOR: purple red + default: + Contract.Assert(false); + throw new InvalidOperationException(); } - return ty; } } @@ -412,6 +413,7 @@ namespace DafnyLanguage case ErrorCategory.InternalError: return TaskErrorCategory.Error; case ErrorCategory.ParseWarning: + case ErrorCategory.ResolveWarning: return TaskErrorCategory.Warning; case ErrorCategory.AuxInformation: return TaskErrorCategory.Message; @@ -477,7 +479,7 @@ namespace DafnyLanguage public enum ErrorCategory { - ProcessError, ParseWarning, ParseError, ResolveError, VerificationError, AuxInformation, InternalError + ProcessError, ParseWarning, ParseError, ResolveWarning, ResolveError, VerificationError, AuxInformation, InternalError } public class DafnyError -- cgit v1.2.3 From d86d8e6d41394166370bdaee4b02fa1ce6886f42 Mon Sep 17 00:00:00 2001 From: Clément Pit--Claudel Date: Fri, 31 Jul 2015 19:09:55 -0700 Subject: Fix an issue with column numbers in the VS extension The error came from the fact that Dafny now consistently used 0-based indexing. Boogie gets its traces from text that's inserted by Dafny in the Boogie file, so there's no need to apply an extra offset in the VS extension. --- Source/DafnyExtension/ResolverTagger.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Source/DafnyExtension/ResolverTagger.cs') diff --git a/Source/DafnyExtension/ResolverTagger.cs b/Source/DafnyExtension/ResolverTagger.cs index 4237041f..6eaec5a6 100644 --- a/Source/DafnyExtension/ResolverTagger.cs +++ b/Source/DafnyExtension/ResolverTagger.cs @@ -529,7 +529,7 @@ namespace DafnyLanguage else { var line = Math.Max(0, int.Parse(match.Groups[1].Value) - 1); - var column = Math.Max(0, int.Parse(match.Groups[2].Value) - 1); + var column = Math.Max(0, int.Parse(match.Groups[2].Value)); var sLine = Snapshot.GetLineFromLineNumber(line); Contract.Assert(column <= sLine.Length); var sLength = Math.Max(0, Math.Min(sLine.Length - column, 0)); -- 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/DafnyExtension/ResolverTagger.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 2f5d59592c5930c32039855824cc49983f643641 Mon Sep 17 00:00:00 2001 From: Clément Pit--Claudel Date: Wed, 19 Aug 2015 16:00:35 -0700 Subject: Enable unicode output in the VS extension --- Source/Dafny/Triggers/QuantifiersCollection.cs | 2 +- Source/DafnyExtension/DafnyDriver.cs | 1 + Source/DafnyExtension/ResolverTagger.cs | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) (limited to 'Source/DafnyExtension/ResolverTagger.cs') diff --git a/Source/Dafny/Triggers/QuantifiersCollection.cs b/Source/Dafny/Triggers/QuantifiersCollection.cs index ecc193fc..a6340f10 100644 --- a/Source/Dafny/Triggers/QuantifiersCollection.cs +++ b/Source/Dafny/Triggers/QuantifiersCollection.cs @@ -156,7 +156,7 @@ namespace Microsoft.Dafny.Triggers { AddTriggersToMessage("Rejected triggers:", q.RejectedCandidates, msg, indent, true); #if QUANTIFIER_WARNINGS - string WARN = (msg.Length > 0 ? indent : "") + (DafnyOptions.O.UnicodeOutput ? "⚠ " : "(!) "); //FIXME set unicodeoutput in extension + string WARN = (msg.Length > 0 ? indent : "") + (DafnyOptions.O.UnicodeOutput ? "⚠ " : "(!) "); if (!q.CandidateTerms.Any()) { errorLevel = ErrorLevel.Warning; msg.Append(WARN).AppendLine("No terms found to trigger on."); diff --git a/Source/DafnyExtension/DafnyDriver.cs b/Source/DafnyExtension/DafnyDriver.cs index 36664a9b..30b0bd52 100644 --- a/Source/DafnyExtension/DafnyDriver.cs +++ b/Source/DafnyExtension/DafnyDriver.cs @@ -40,6 +40,7 @@ namespace DafnyLanguage options.ErrorTrace = 0; options.VcsCores = Math.Max(1, System.Environment.ProcessorCount - 1); options.ModelViewFile = "-"; + options.UnicodeOutput = true; Dafny.DafnyOptions.Install(options); // Read additional options from DafnyOptions.txt diff --git a/Source/DafnyExtension/ResolverTagger.cs b/Source/DafnyExtension/ResolverTagger.cs index 0ce68809..22706338 100644 --- a/Source/DafnyExtension/ResolverTagger.cs +++ b/Source/DafnyExtension/ResolverTagger.cs @@ -403,7 +403,7 @@ namespace DafnyLanguage chng(this, new SnapshotSpanEventArgs(new SnapshotSpan(snapshot, 0, snapshot.Length))); } - static TaskErrorCategory CategoryConversion(ErrorCategory cat) //CLEMENT: We've lost that info + static TaskErrorCategory CategoryConversion(ErrorCategory cat) { switch (cat) { -- cgit v1.2.3 From c5094e85c027730aa0ef6466766a8e5c99d83c11 Mon Sep 17 00:00:00 2001 From: wuestholz Date: Thu, 8 Oct 2015 12:26:37 -0500 Subject: DafnyExtension: Fix concurrency issue. --- Source/DafnyExtension/ResolverTagger.cs | 79 ++++++++++++++++----------------- 1 file changed, 38 insertions(+), 41 deletions(-) (limited to 'Source/DafnyExtension/ResolverTagger.cs') diff --git a/Source/DafnyExtension/ResolverTagger.cs b/Source/DafnyExtension/ResolverTagger.cs index 22706338..b348e7d6 100644 --- a/Source/DafnyExtension/ResolverTagger.cs +++ b/Source/DafnyExtension/ResolverTagger.cs @@ -189,7 +189,7 @@ namespace DafnyLanguage { get { - return _verificationErrors.Values.Where(ec => ec.RequestId == MostRecentRequestId).SelectMany(ec => ec.Errors.Reverse()); + return _verificationErrors.Values.Where(ec => ec.RequestId == MostRecentRequestId).SelectMany(ec => ec.Errors.Reverse()).ToList(); } } @@ -354,49 +354,46 @@ namespace DafnyLanguage public void UpdateErrorList(ITextSnapshot snapshot) { - lock (this) + if (_errorProvider != null && !m_disposed) { - if (_errorProvider != null && !m_disposed) - { - _errorProvider.SuspendRefresh(); // reduce flickering - _errorProvider.Tasks.Clear(); - foreach (var err in AllErrors) - { - var lineNum = 0; - var columnNum = 0; - if (err.Span != null) { - var span = err.Span.GetSpan(snapshot); - lineNum = snapshot.GetLineNumberFromPosition(span.Start.Position); - var line = snapshot.GetLineFromPosition(span.Start.Position); - columnNum = span.Start - line.Start; - } else { - lineNum = err.Line; - columnNum = err.Column; - } - - ErrorTask task = new ErrorTask() - { - Category = TaskCategory.BuildCompile, - ErrorCategory = CategoryConversion(err.Category), - Text = err.Message, - Line = lineNum, - Column = columnNum - }; - if (err.Filename != null) { - task.Document = err.Filename; - } - else if (_document != null) - { - task.Document = _document.FilePath; - } - if (err.Category != ErrorCategory.ProcessError && err.Category != ErrorCategory.InternalError) - { - task.Navigate += new EventHandler(NavigateHandler); - } - _errorProvider.Tasks.Add(task); + _errorProvider.SuspendRefresh(); // reduce flickering + _errorProvider.Tasks.Clear(); + foreach (var err in AllErrors) + { + var lineNum = 0; + var columnNum = 0; + if (err.Span != null) { + var span = err.Span.GetSpan(snapshot); + lineNum = snapshot.GetLineNumberFromPosition(span.Start.Position); + var line = snapshot.GetLineFromPosition(span.Start.Position); + columnNum = span.Start - line.Start; + } else { + lineNum = err.Line; + columnNum = err.Column; + } + + ErrorTask task = new ErrorTask() + { + Category = TaskCategory.BuildCompile, + ErrorCategory = CategoryConversion(err.Category), + Text = err.Message, + Line = lineNum, + Column = columnNum + }; + if (err.Filename != null) { + task.Document = err.Filename; + } + else if (_document != null) + { + task.Document = _document.FilePath; + } + if (err.Category != ErrorCategory.ProcessError && err.Category != ErrorCategory.InternalError) + { + task.Navigate += new EventHandler(NavigateHandler); } - _errorProvider.ResumeRefresh(); + _errorProvider.Tasks.Add(task); } + _errorProvider.ResumeRefresh(); } var chng = TagsChanged; if (chng != null) -- cgit v1.2.3 From 516f8a5ab59dd2bf7c813b09824a7e2cda004538 Mon Sep 17 00:00:00 2001 From: leino Date: Sat, 24 Oct 2015 18:38:16 -0700 Subject: In Visual Studio, be willing to display both resolution warnings and verification errors (previously, verification errors were masked by resolution warnings) --- Source/DafnyExtension/ResolverTagger.cs | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) (limited to 'Source/DafnyExtension/ResolverTagger.cs') diff --git a/Source/DafnyExtension/ResolverTagger.cs b/Source/DafnyExtension/ResolverTagger.cs index b348e7d6..58a46196 100644 --- a/Source/DafnyExtension/ResolverTagger.cs +++ b/Source/DafnyExtension/ResolverTagger.cs @@ -199,13 +199,19 @@ namespace DafnyLanguage { lock (this) { - if (_resolutionErrors != null && _resolutionErrors.Any()) - { - return _resolutionErrors; + bool anyResolutionErrors = false; + if (_resolutionErrors != null) { + foreach (var err in _resolutionErrors) { + if (CategoryConversion(err.Category) == TaskErrorCategory.Error) { + anyResolutionErrors = true; + } + yield return err; + } } - else - { - return VerificationErrors; + if (!anyResolutionErrors) { + foreach (var err in VerificationErrors) { + yield return err; + } } } } -- cgit v1.2.3 From 8f244896640bae196070aa8b2bfe0b2f0be24e2a Mon Sep 17 00:00:00 2001 From: qunyanm Date: Wed, 20 Jan 2016 16:25:46 -0800 Subject: VS IDE performance - invoke dafny parser when the buffer hasn't changed for half a second, but delay calling Dafny resolver until the text buffer hasn't been changed for 5 seconds. Also save the parsing result from TokenTagger in ITextBuffer's property instead of in a static field. --- Source/DafnyExtension/DafnyDriver.cs | 49 +++++++++++++++++++++++---------- Source/DafnyExtension/ResolverTagger.cs | 37 +++++++++++++++++++++---- Source/DafnyExtension/TokenTagger.cs | 31 ++++++++++----------- 3 files changed, 82 insertions(+), 35 deletions(-) (limited to 'Source/DafnyExtension/ResolverTagger.cs') diff --git a/Source/DafnyExtension/DafnyDriver.cs b/Source/DafnyExtension/DafnyDriver.cs index 27471d56..037d0cd3 100644 --- a/Source/DafnyExtension/DafnyDriver.cs +++ b/Source/DafnyExtension/DafnyDriver.cs @@ -18,13 +18,16 @@ namespace DafnyLanguage { readonly string _filename; readonly ITextSnapshot _snapshot; + readonly ITextBuffer _buffer; Dafny.Program _program; + static object bufferDafnyKey = new object(); List _errors = new List(); public List Errors { get { return _errors; } } - public DafnyDriver(ITextSnapshot snapshot, string filename) { - _snapshot = snapshot; + public DafnyDriver(ITextBuffer buffer, string filename) { + _buffer = buffer; + _snapshot = buffer.CurrentSnapshot; _filename = filename; } @@ -107,25 +110,42 @@ namespace DafnyLanguage #region Parsing and type checking - internal Dafny.Program ProcessResolution() { - if (!ParseAndTypeCheck()) { + internal Dafny.Program ProcessResolution(bool runResolver) { + if (!ParseAndTypeCheck(runResolver)) { return null; } return _program; } - bool ParseAndTypeCheck() { - Dafny.ModuleDecl module = new Dafny.LiteralModuleDecl(new Dafny.DefaultModuleDecl(), null); - Dafny.BuiltIns builtIns = new Dafny.BuiltIns(); - + bool ParseAndTypeCheck(bool runResolver) { + Tuple> parseResult; + Dafny.Program program; 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) + if (_buffer.Properties.TryGetProperty(bufferDafnyKey, out parseResult) && + (parseResult.Item1 == _snapshot)) { + // already parsed; + program = parseResult.Item2; + _errors = parseResult.Item3; + if (program == null) + runResolver = false; + } else { + Dafny.ModuleDecl module = new Dafny.LiteralModuleDecl(new Dafny.DefaultModuleDecl(), null); + Dafny.BuiltIns builtIns = new Dafny.BuiltIns(); + 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) { + runResolver = false; + program = null; + } else { + program = new Dafny.Program(_filename, module, builtIns, errorReporter); + } + _buffer.Properties[bufferDafnyKey] = new Tuple>(_snapshot, program, _errors); + } + if (!runResolver) { return false; - Dafny.Program program = new Dafny.Program(_filename, module, builtIns, errorReporter); + } var r = new Resolver(program); r.ResolveProgram(program); @@ -136,6 +156,7 @@ namespace DafnyLanguage return true; // success } + void RecordError(string filename, int line, int col, ErrorCategory cat, string msg, bool isRecycled = false) { _errors.Add(new DafnyError(filename, line - 1, col - 1, cat, msg, _snapshot, isRecycled, null, System.IO.Path.GetFullPath(this._filename) == filename)); diff --git a/Source/DafnyExtension/ResolverTagger.cs b/Source/DafnyExtension/ResolverTagger.cs index 58a46196..b711c276 100644 --- a/Source/DafnyExtension/ResolverTagger.cs +++ b/Source/DafnyExtension/ResolverTagger.cs @@ -15,6 +15,7 @@ using System.Linq; using System.Text.RegularExpressions; using System.Windows.Shapes; using Microsoft.VisualStudio; +using System.Windows.Threading; using Microsoft.VisualStudio.Shell; using Microsoft.VisualStudio.Shell.Interop; using Microsoft.VisualStudio.Text; @@ -129,6 +130,8 @@ namespace DafnyLanguage ErrorListProvider _errorProvider; private bool m_disposed; + readonly DispatcherTimer timer; + // The 'Snapshot' and 'Program' fields should be updated and read together, so they are protected by "this" public ITextSnapshot Snapshot; // may be null public Dafny.Program Program; // non-null only if the snapshot contains a Dafny program that type checks @@ -227,7 +230,13 @@ namespace DafnyLanguage Snapshot = null; // this makes sure the next snapshot will look different _errorProvider = new ErrorListProvider(serviceProvider); - BufferIdleEventUtil.AddBufferIdleEventListener(_buffer, ResolveBuffer); + BufferIdleEventUtil.AddBufferIdleEventListener(_buffer, UponIdle); + + // keep track idle time after BufferIdleEvent has been handled. + timer = new DispatcherTimer(DispatcherPriority.ApplicationIdle); + timer.Interval = TimeSpan.FromMilliseconds(5000); + timer.Tick += new EventHandler(ResolveBuffer); + buffer.Changed += BufferChanged; } public void Dispose() @@ -257,7 +266,9 @@ namespace DafnyLanguage _errorProvider.Dispose(); _errorProvider = null; } - BufferIdleEventUtil.RemoveBufferIdleEventListener(_buffer, ResolveBuffer); + BufferIdleEventUtil.RemoveBufferIdleEventListener(_buffer, UponIdle); + timer.Tick -= ResolveBuffer; + _buffer.Changed -= BufferChanged; if (_document != null && _document.TextBuffer != null) { ResolverTaggers.Remove(_document.TextBuffer); @@ -319,17 +330,28 @@ namespace DafnyLanguage /// void ResolveBuffer(object sender, EventArgs args) { + timer.Stop(); + ParseAndResolveBuffer(sender, args, true); + } + + void UponIdle(object sender, EventArgs args) { + timer.Stop(); + ParseAndResolveBuffer(sender, args, false); + timer.Start(); + } + + void ParseAndResolveBuffer(object sender, EventArgs args, bool runResolver) { ITextSnapshot snapshot = _buffer.CurrentSnapshot; - if (snapshot == Snapshot) + if (snapshot == Snapshot && !runResolver) return; // we've already done this snapshot string filename = _document != null ? _document.FilePath : ""; - var driver = new DafnyDriver(snapshot, filename); + var driver = new DafnyDriver(_buffer, filename); List newErrors; Dafny.Program program; try { - program = driver.ProcessResolution(); + program = driver.ProcessResolution(runResolver); newErrors = driver.Errors; } catch (Exception e) @@ -358,6 +380,11 @@ namespace DafnyLanguage UpdateErrorList(snapshot); } + void BufferChanged(object sender, TextContentChangedEventArgs e) { + timer.Stop(); + timer.Start(); + } + public void UpdateErrorList(ITextSnapshot snapshot) { if (_errorProvider != null && !m_disposed) diff --git a/Source/DafnyExtension/TokenTagger.cs b/Source/DafnyExtension/TokenTagger.cs index f1c4860c..7a5eb572 100644 --- a/Source/DafnyExtension/TokenTagger.cs +++ b/Source/DafnyExtension/TokenTagger.cs @@ -91,10 +91,7 @@ namespace DafnyLanguage ITextBuffer _buffer; ITextSnapshot _snapshot; List _regions; - // TODO: instead of storing the scan result in the static field and shared by the different - // instances of DafnyTokenTagger, could it be associated to the TextBuffer using - // ITextBuffer.Properties.GetOrCreateSingletonProperty? - static ScanResult _scanResult = null; + static object bufferTokenTaggerKey = new object(); bool _disposed; internal DafnyTokenTagger(ITextBuffer buffer) { @@ -109,10 +106,10 @@ namespace DafnyLanguage lock (this) { if (!_disposed) { _buffer.Changed -= ReparseFile; + _buffer.Properties.RemoveProperty(bufferTokenTaggerKey); _buffer = null; _snapshot = null; _regions = null; - _scanResult = null; _disposed = true; } } @@ -150,12 +147,13 @@ namespace DafnyLanguage return; // we've already computed the regions for this snapshot NormalizedSnapshotSpanCollection difference = new NormalizedSnapshotSpanCollection(); - if (DafnyTokenTagger._scanResult != null && - DafnyTokenTagger._scanResult._oldSnapshot == _snapshot && - DafnyTokenTagger._scanResult._newSnapshot == snapshot) { - difference = DafnyTokenTagger._scanResult._difference; + ScanResult result; + if (_buffer.Properties.TryGetProperty(bufferTokenTaggerKey, out result) && + (result._oldSnapshot == _snapshot) && + (result._newSnapshot == snapshot)) { + difference = result._difference; // save the new baseline - _regions = DafnyTokenTagger._scanResult._regions; + _regions = result._regions; _snapshot = snapshot; } else { List regions = new List(); @@ -229,7 +227,7 @@ namespace DafnyLanguage difference = SymmetricDifference(oldSpanCollection, newSpanCollection); // save the scan result - DafnyTokenTagger._scanResult = new ScanResult(_snapshot, snapshot, regions, difference); + _buffer.Properties[bufferTokenTaggerKey] = new ScanResult(_snapshot, snapshot, regions, difference); // save the new baseline _snapshot = snapshot; _regions = regions; @@ -468,11 +466,12 @@ namespace DafnyLanguage return new SnapshotPoint(newSnapshot, start + N); } - private static List Scan(ITextSnapshot newSnapshot) { + private List Scan(ITextSnapshot newSnapshot) { List newRegions; - if (DafnyTokenTagger._scanResult != null && - DafnyTokenTagger._scanResult._newSnapshot == newSnapshot) { - newRegions = DafnyTokenTagger._scanResult._regions; + ScanResult result; + if (_buffer.Properties.TryGetProperty(bufferTokenTaggerKey, out result) && + result._newSnapshot == newSnapshot) { + newRegions = result._regions; } else { newRegions = new List(); int nextLineNumber = -1; @@ -485,7 +484,7 @@ namespace DafnyLanguage SnapshotPoint end = Scan(txt, line.Start, newRegions, newSnapshot); nextLineNumber = newSnapshot.GetLineFromPosition(end).LineNumber; } - DafnyTokenTagger._scanResult = new ScanResult(null, newSnapshot, newRegions, null); + _buffer.Properties[bufferTokenTaggerKey] = new ScanResult(null, newSnapshot, newRegions, null); } return newRegions; } -- cgit v1.2.3 From 45e7bb72d4a8676796cb71cd8d11787dd6f91e17 Mon Sep 17 00:00:00 2001 From: qunyanm Date: Mon, 29 Feb 2016 12:44:54 -0800 Subject: Revert change 1997 (bfe7c149bef1). IDE performance. Don't delay the resolver until the editor is idle for 5 second. --- Source/DafnyExtension/ResolverTagger.cs | 38 +++++---------------------------- 1 file changed, 5 insertions(+), 33 deletions(-) (limited to 'Source/DafnyExtension/ResolverTagger.cs') diff --git a/Source/DafnyExtension/ResolverTagger.cs b/Source/DafnyExtension/ResolverTagger.cs index b711c276..4a50a4e8 100644 --- a/Source/DafnyExtension/ResolverTagger.cs +++ b/Source/DafnyExtension/ResolverTagger.cs @@ -15,7 +15,6 @@ using System.Linq; using System.Text.RegularExpressions; using System.Windows.Shapes; using Microsoft.VisualStudio; -using System.Windows.Threading; using Microsoft.VisualStudio.Shell; using Microsoft.VisualStudio.Shell.Interop; using Microsoft.VisualStudio.Text; @@ -130,8 +129,6 @@ namespace DafnyLanguage ErrorListProvider _errorProvider; private bool m_disposed; - readonly DispatcherTimer timer; - // The 'Snapshot' and 'Program' fields should be updated and read together, so they are protected by "this" public ITextSnapshot Snapshot; // may be null public Dafny.Program Program; // non-null only if the snapshot contains a Dafny program that type checks @@ -230,13 +227,7 @@ namespace DafnyLanguage Snapshot = null; // this makes sure the next snapshot will look different _errorProvider = new ErrorListProvider(serviceProvider); - BufferIdleEventUtil.AddBufferIdleEventListener(_buffer, UponIdle); - - // keep track idle time after BufferIdleEvent has been handled. - timer = new DispatcherTimer(DispatcherPriority.ApplicationIdle); - timer.Interval = TimeSpan.FromMilliseconds(5000); - timer.Tick += new EventHandler(ResolveBuffer); - buffer.Changed += BufferChanged; + BufferIdleEventUtil.AddBufferIdleEventListener(_buffer, ResolveBuffer); } public void Dispose() @@ -266,9 +257,7 @@ namespace DafnyLanguage _errorProvider.Dispose(); _errorProvider = null; } - BufferIdleEventUtil.RemoveBufferIdleEventListener(_buffer, UponIdle); - timer.Tick -= ResolveBuffer; - _buffer.Changed -= BufferChanged; + BufferIdleEventUtil.RemoveBufferIdleEventListener(_buffer, ResolveBuffer); if (_document != null && _document.TextBuffer != null) { ResolverTaggers.Remove(_document.TextBuffer); @@ -328,21 +317,9 @@ namespace DafnyLanguage /// /// Calls the Dafny parser/resolver/type checker on the contents of the buffer, updates the Error List accordingly. /// - void ResolveBuffer(object sender, EventArgs args) - { - timer.Stop(); - ParseAndResolveBuffer(sender, args, true); - } - - void UponIdle(object sender, EventArgs args) { - timer.Stop(); - ParseAndResolveBuffer(sender, args, false); - timer.Start(); - } - - void ParseAndResolveBuffer(object sender, EventArgs args, bool runResolver) { + void ResolveBuffer(object sender, EventArgs args) { ITextSnapshot snapshot = _buffer.CurrentSnapshot; - if (snapshot == Snapshot && !runResolver) + if (snapshot == Snapshot) return; // we've already done this snapshot string filename = _document != null ? _document.FilePath : ""; @@ -351,7 +328,7 @@ namespace DafnyLanguage Dafny.Program program; try { - program = driver.ProcessResolution(runResolver); + program = driver.ProcessResolution(true); newErrors = driver.Errors; } catch (Exception e) @@ -380,11 +357,6 @@ namespace DafnyLanguage UpdateErrorList(snapshot); } - void BufferChanged(object sender, TextContentChangedEventArgs e) { - timer.Stop(); - timer.Start(); - } - public void UpdateErrorList(ITextSnapshot snapshot) { if (_errorProvider != null && !m_disposed) -- cgit v1.2.3