From 10a8896ae40fd918abbb8caa616ac6ee0876ac1d Mon Sep 17 00:00:00 2001 From: qunyanm Date: Fri, 29 May 2015 16:29:15 -0700 Subject: Add an infinite set collection type. --- Source/Dafny/Scanner.cs | 300 +++++++++++++++++++++++++----------------------- 1 file changed, 156 insertions(+), 144 deletions(-) (limited to 'Source/Dafny/Scanner.cs') diff --git a/Source/Dafny/Scanner.cs b/Source/Dafny/Scanner.cs index 3427477b..4c5eedb4 100644 --- a/Source/Dafny/Scanner.cs +++ b/Source/Dafny/Scanner.cs @@ -211,13 +211,13 @@ public class UTF8Buffer: Buffer { public class Scanner { const char EOL = '\n'; const int eofSym = 0; /* pdt */ - const int maxT = 136; - const int noSym = 136; + const int maxT = 137; + const int noSym = 137; [ContractInvariantMethod] void objectInvariant(){ - Contract.Invariant(buffer!=null); + Contract.Invariant(this._buffer != null); Contract.Invariant(t != null); Contract.Invariant(start != null); Contract.Invariant(tokens != null); @@ -227,7 +227,18 @@ public class Scanner { Contract.Invariant(errorHandler != null); } - public Buffer/*!*/ buffer; // scanner buffer + private Buffer/*!*/ _buffer; // scanner buffer + + public Buffer/*!*/ buffer { + get { + Contract.Ensures(Contract.Result() != null); + return this._buffer; + } + set { + Contract.Requires(value != null); + this._buffer = value; + } + } Token/*!*/ t; // current token int ch; // current input character @@ -307,7 +318,7 @@ public class Scanner { t = new Token(); // dummy because t is a non-null field try { Stream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read); - buffer = new Buffer(stream, false); + this._buffer = new Buffer(stream, false); Filename = useBaseName? GetBaseName(fileName): fileName; Init(); } catch (IOException) { @@ -322,7 +333,7 @@ public class Scanner { Contract.Requires(fileName != null); pt = tokens = new Token(); // first token is a dummy t = new Token(); // dummy because t is a non-null field - buffer = new Buffer(s, true); + this._buffer = new Buffer(s, true); this.errorHandler = errorHandler; this.Filename = useBaseName? GetBaseName(fileName) : fileName; Init(); @@ -503,75 +514,76 @@ public class Scanner { case "object": t.kind = 11; break; case "string": t.kind = 12; break; case "set": t.kind = 13; break; - case "multiset": t.kind = 14; break; - case "seq": t.kind = 15; break; - case "map": t.kind = 16; break; - case "imap": t.kind = 17; break; - case "assume": t.kind = 29; break; - case "calc": t.kind = 30; break; - case "case": t.kind = 31; break; - case "then": t.kind = 32; break; - case "else": t.kind = 33; break; - case "decreases": t.kind = 34; break; - case "invariant": t.kind = 35; break; - case "function": t.kind = 36; break; - case "predicate": t.kind = 37; break; - case "inductive": t.kind = 38; break; - case "lemma": t.kind = 39; break; - case "copredicate": t.kind = 40; break; - case "modifies": t.kind = 41; break; - case "reads": t.kind = 42; break; - case "requires": t.kind = 43; break; - case "include": t.kind = 58; break; - case "abstract": t.kind = 59; break; - case "module": t.kind = 60; break; - case "refines": t.kind = 61; break; - case "import": t.kind = 62; break; - case "opened": t.kind = 63; break; - case "as": t.kind = 65; break; - case "default": t.kind = 66; break; - case "class": t.kind = 67; break; - case "extends": t.kind = 68; break; - case "trait": t.kind = 69; break; - case "ghost": t.kind = 70; break; - case "static": t.kind = 71; break; - case "protected": t.kind = 72; break; - case "datatype": t.kind = 73; break; - case "codatatype": t.kind = 74; break; - case "var": t.kind = 75; break; - case "newtype": t.kind = 76; break; - case "type": t.kind = 77; break; - case "iterator": t.kind = 78; break; - case "yields": t.kind = 79; break; - case "returns": t.kind = 80; break; - case "method": t.kind = 81; break; - case "colemma": t.kind = 82; break; - case "comethod": t.kind = 83; break; - case "constructor": t.kind = 84; break; - case "free": t.kind = 85; break; - case "ensures": t.kind = 86; break; - case "yield": t.kind = 87; break; - case "label": t.kind = 89; break; - case "break": t.kind = 90; break; - case "where": t.kind = 91; break; - case "return": t.kind = 93; break; - case "new": t.kind = 95; break; - case "if": t.kind = 96; break; - case "while": t.kind = 97; break; - case "match": t.kind = 98; break; - case "assert": t.kind = 99; break; - case "print": t.kind = 100; break; - case "forall": t.kind = 101; break; - case "parallel": t.kind = 102; break; - case "modify": t.kind = 103; break; - case "exists": t.kind = 122; break; - case "in": t.kind = 124; break; - case "false": t.kind = 129; break; - case "true": t.kind = 130; break; - case "null": t.kind = 131; break; - case "this": t.kind = 132; break; - case "fresh": t.kind = 133; break; - case "old": t.kind = 134; break; + case "iset": t.kind = 14; break; + case "multiset": t.kind = 15; break; + case "seq": t.kind = 16; break; + case "map": t.kind = 17; break; + case "imap": t.kind = 18; break; + case "assume": t.kind = 30; break; + case "calc": t.kind = 31; break; + case "case": t.kind = 32; break; + case "then": t.kind = 33; break; + case "else": t.kind = 34; break; + case "decreases": t.kind = 35; break; + case "invariant": t.kind = 36; break; + case "function": t.kind = 37; break; + case "predicate": t.kind = 38; break; + case "inductive": t.kind = 39; break; + case "lemma": t.kind = 40; break; + case "copredicate": t.kind = 41; break; + case "modifies": t.kind = 42; break; + case "reads": t.kind = 43; break; + case "requires": t.kind = 44; break; + case "include": t.kind = 59; break; + case "abstract": t.kind = 60; break; + case "module": t.kind = 61; break; + case "refines": t.kind = 62; break; + case "import": t.kind = 63; break; + case "opened": t.kind = 64; break; + case "as": t.kind = 66; break; + case "default": t.kind = 67; break; + case "class": t.kind = 68; break; + case "extends": t.kind = 69; break; + case "trait": t.kind = 70; break; + case "ghost": t.kind = 71; break; + case "static": t.kind = 72; break; + case "protected": t.kind = 73; break; + case "datatype": t.kind = 74; break; + case "codatatype": t.kind = 75; break; + case "var": t.kind = 76; break; + case "newtype": t.kind = 77; break; + case "type": t.kind = 78; break; + case "iterator": t.kind = 79; break; + case "yields": t.kind = 80; break; + case "returns": t.kind = 81; break; + case "method": t.kind = 82; break; + case "colemma": t.kind = 83; break; + case "comethod": t.kind = 84; break; + case "constructor": t.kind = 85; break; + case "free": t.kind = 86; break; + case "ensures": t.kind = 87; break; + case "yield": t.kind = 88; break; + case "label": t.kind = 90; break; + case "break": t.kind = 91; break; + case "where": t.kind = 92; break; + case "return": t.kind = 94; break; + case "new": t.kind = 96; break; + case "if": t.kind = 97; break; + case "while": t.kind = 98; break; + case "match": t.kind = 99; break; + case "assert": t.kind = 100; break; + case "print": t.kind = 101; break; + case "forall": t.kind = 102; break; + case "parallel": t.kind = 103; break; + case "modify": t.kind = 104; break; + case "exists": t.kind = 123; break; + case "in": t.kind = 125; break; + case "false": t.kind = 130; break; + case "true": t.kind = 131; break; + case "null": t.kind = 132; break; + case "this": t.kind = 133; break; + case "fresh": t.kind = 134; break; + case "old": t.kind = 135; break; default: break; } } @@ -674,7 +686,7 @@ public class Scanner { if (ch >= '0' && ch <= '9' || ch >= 'A' && ch <= 'F' || ch >= 'a' && ch <= 'f') {AddCh(); goto case 15;} else {goto case 0;} case 20: - {t.kind = 18; break;} + {t.kind = 19; break;} case 21: if (ch <= 9 || ch >= 11 && ch <= 12 || ch >= 14 && ch <= '!' || ch >= '#' && ch <= '[' || ch >= ']' && ch <= 65535) {AddCh(); goto case 21;} else if (ch == '"') {AddCh(); goto case 28;} @@ -700,37 +712,37 @@ public class Scanner { else if (ch == '"') {AddCh(); goto case 55;} else {goto case 0;} case 28: - {t.kind = 19; break;} + {t.kind = 20; break;} case 29: - {t.kind = 21; break;} + {t.kind = 22; break;} case 30: - {t.kind = 23; break;} - case 31: {t.kind = 24; break;} + case 31: + {t.kind = 25; break;} case 32: - {t.kind = 26; break;} - case 33: {t.kind = 27; break;} - case 34: + case 33: {t.kind = 28; break;} + case 34: + {t.kind = 29; break;} case 35: - {t.kind = 44; break;} - case 36: {t.kind = 45; break;} - case 37: + case 36: {t.kind = 46; break;} - case 38: + case 37: {t.kind = 47; break;} - case 39: + case 38: {t.kind = 48; break;} - case 40: + case 39: {t.kind = 49; break;} + case 40: + {t.kind = 50; break;} case 41: - {t.kind = 53; break;} - case 42: {t.kind = 54; break;} - case 43: + case 42: {t.kind = 55; break;} + case 43: + {t.kind = 56; break;} case 44: if (ch == 'n') {AddCh(); goto case 45;} else {goto case 0;} @@ -741,9 +753,9 @@ public class Scanner { { tlen -= apx; SetScannerBehindT(); - t.kind = 56; break;} + t.kind = 57; break;} case 47: - {t.kind = 57; break;} + {t.kind = 58; break;} case 48: recEnd = pos; recKind = 2; if (ch >= '0' && ch <= '9') {AddCh(); goto case 48;} @@ -782,9 +794,9 @@ public class Scanner { else if (ch == 'u') {AddCh(); goto case 22;} else {goto case 0;} case 55: - recEnd = pos; recKind = 19; + recEnd = pos; recKind = 20; if (ch == '"') {AddCh(); goto case 27;} - else {t.kind = 19; break;} + else {t.kind = 20; break;} case 56: if (ch >= '0' && ch <= '9') {AddCh(); goto case 48;} else {goto case 0;} @@ -813,9 +825,9 @@ public class Scanner { if (ch == 39 || ch >= '0' && ch <= '9' || ch == '?' || ch >= 'A' && ch <= 'Z' || ch == '_' || ch >= 'a' && ch <= 'z') {AddCh(); goto case 8;} else {t.kind = 1; t.val = new String(tval, 0, tlen); CheckLiteral(); return t;} case 62: - recEnd = pos; recKind = 18; + recEnd = pos; recKind = 19; if (ch == 39 || ch >= '0' && ch <= '9' || ch == '?' || ch >= 'A' && ch <= 'Z' || ch == '_' || ch >= 'a' && ch <= 'z') {AddCh(); goto case 8;} - else {t.kind = 18; break;} + else {t.kind = 19; break;} case 63: recEnd = pos; recKind = 1; if (ch == 39 || ch >= '0' && ch <= '9' || ch == '?' || ch >= 'A' && ch <= 'Z' || ch == '_' || ch >= 'a' && ch <= 'x' || ch == 'z') {AddCh(); goto case 5;} @@ -832,104 +844,104 @@ public class Scanner { else if (ch >= '0' && ch <= '9') {AddCh(); goto case 65;} else {t.kind = 5; break;} case 66: - {t.kind = 88; break;} + {t.kind = 89; break;} case 67: - {t.kind = 92; break;} + {t.kind = 93; break;} case 68: - {t.kind = 94; break;} + {t.kind = 95; break;} case 69: - {t.kind = 104; break;} + {t.kind = 105; break;} case 70: - {t.kind = 106; break;} - case 71: {t.kind = 107; break;} - case 72: + case 71: {t.kind = 108; break;} - case 73: + case 72: {t.kind = 109; break;} - case 74: + case 73: {t.kind = 110; break;} - case 75: + case 74: {t.kind = 111; break;} - case 76: + case 75: {t.kind = 112; break;} + case 76: + {t.kind = 113; break;} case 77: - {t.kind = 114; break;} + {t.kind = 115; break;} case 78: if (ch == '&') {AddCh(); goto case 79;} else {goto case 0;} case 79: - {t.kind = 115; break;} - case 80: {t.kind = 116; break;} - case 81: + case 80: {t.kind = 117; break;} - case 82: + case 81: {t.kind = 118; break;} + case 82: + {t.kind = 119; break;} case 83: - {t.kind = 120; break;} - case 84: {t.kind = 121; break;} + case 84: + {t.kind = 122; break;} case 85: - {t.kind = 123; break;} + {t.kind = 124; break;} case 86: - {t.kind = 125; break;} + {t.kind = 126; break;} case 87: - {t.kind = 127; break;} - case 88: {t.kind = 128; break;} + case 88: + {t.kind = 129; break;} case 89: - recEnd = pos; recKind = 20; + recEnd = pos; recKind = 21; if (ch == ':') {AddCh(); goto case 30;} else if (ch == '=') {AddCh(); goto case 67;} else if (ch == '|') {AddCh(); goto case 68;} - else {t.kind = 20; break;} + else {t.kind = 21; break;} case 90: - recEnd = pos; recKind = 22; + recEnd = pos; recKind = 23; if (ch == '|') {AddCh(); goto case 81;} - else {t.kind = 22; break;} + else {t.kind = 23; break;} case 91: - recEnd = pos; recKind = 25; + recEnd = pos; recKind = 26; if (ch == '.') {AddCh(); goto case 97;} - else {t.kind = 25; break;} + else {t.kind = 26; break;} case 92: - recEnd = pos; recKind = 64; + recEnd = pos; recKind = 65; if (ch == '>') {AddCh(); goto case 33;} else if (ch == '=') {AddCh(); goto case 98;} - else {t.kind = 64; break;} + else {t.kind = 65; break;} case 93: - recEnd = pos; recKind = 126; + recEnd = pos; recKind = 127; if (ch == '>') {AddCh(); goto case 34;} - else {t.kind = 126; break;} + else {t.kind = 127; break;} case 94: - recEnd = pos; recKind = 50; + recEnd = pos; recKind = 51; if (ch == '=') {AddCh(); goto case 99;} - else {t.kind = 50; break;} + else {t.kind = 51; break;} case 95: - recEnd = pos; recKind = 51; + recEnd = pos; recKind = 52; if (ch == '=') {AddCh(); goto case 70;} - else {t.kind = 51; break;} + else {t.kind = 52; break;} case 96: - recEnd = pos; recKind = 119; + recEnd = pos; recKind = 120; if (ch == '=') {AddCh(); goto case 41;} else if (ch == 'i') {AddCh(); goto case 44;} - else {t.kind = 119; break;} + else {t.kind = 120; break;} case 97: - recEnd = pos; recKind = 135; + recEnd = pos; recKind = 136; if (ch == '.') {AddCh(); goto case 47;} - else {t.kind = 135; break;} + else {t.kind = 136; break;} case 98: - recEnd = pos; recKind = 52; + recEnd = pos; recKind = 53; if (ch == '>') {AddCh(); goto case 75;} - else {t.kind = 52; break;} + else {t.kind = 53; break;} case 99: - recEnd = pos; recKind = 105; + recEnd = pos; recKind = 106; if (ch == '=') {AddCh(); goto case 100;} - else {t.kind = 105; break;} + else {t.kind = 106; break;} case 100: - recEnd = pos; recKind = 113; + recEnd = pos; recKind = 114; if (ch == '>') {AddCh(); goto case 73;} - else {t.kind = 113; break;} + else {t.kind = 114; break;} } t.val = new String(tval, 0, tlen); -- cgit v1.2.3 From 5b3dcd0c09a7ea8a34e7f5e4b8800015b3b07e96 Mon Sep 17 00:00:00 2001 From: Bryan Parno Date: Wed, 1 Jul 2015 12:37:54 -0700 Subject: Add the ability to specify how much "fuel" a function should have, i.e., how many times Z3 is permitted to unfold it's definition. The new {:fuel} annotation can be added to the function itself, it which case it will apply to all uses of that function, or it can overridden within the scope of a module, function, method, iterator, calc, forall, while, assert, or assume. The general format is: {:fuel functionName,lowFuel,highFuel} When applied as an annotation to the function itself, omit functionName. If highFuel is omitted, it defaults to lowFuel + 1. The default fuel setting for recursive functions is 1,2. Setting the fuel higher, say, to 3,4, will give more unfoldings, which may make some proofs go through with less programmer assistance (e.g., with fewer assert statements), but it may also increase verification time, so use it with care. Setting the fuel to 0,0 is similar to making the definition opaque, except when used with all literal arguments. --- Source/Dafny/Cloner.cs | 2 +- Source/Dafny/Dafny.atg | 4 +- Source/Dafny/DafnyAst.cs | 25 ++- Source/Dafny/Parser.cs | 78 ++++---- Source/Dafny/Resolver.cs | 74 +++++++- Source/Dafny/Scanner.cs | 31 +--- Source/Dafny/Translator.cs | 388 ++++++++++++++++++++++++++++++---------- Test/dafny0/Fuel.dfy | 423 ++++++++++++++++++++++++++++++++++++++++++++ Test/dafny0/Fuel.dfy.expect | 95 ++++++++++ Test/dafny4/Circ.dfy | 2 + 10 files changed, 967 insertions(+), 155 deletions(-) create mode 100644 Test/dafny0/Fuel.dfy create mode 100644 Test/dafny0/Fuel.dfy.expect (limited to 'Source/Dafny/Scanner.cs') diff --git a/Source/Dafny/Cloner.cs b/Source/Dafny/Cloner.cs index f13aa2f4..e313ffac 100644 --- a/Source/Dafny/Cloner.cs +++ b/Source/Dafny/Cloner.cs @@ -545,7 +545,7 @@ namespace Microsoft.Dafny } else if (stmt is CalcStmt) { var s = (CalcStmt)stmt; - r = new CalcStmt(Tok(s.Tok), Tok(s.EndTok), CloneCalcOp(s.Op), s.Lines.ConvertAll(CloneExpr), s.Hints.ConvertAll(CloneBlockStmt), s.StepOps.ConvertAll(CloneCalcOp), CloneCalcOp(s.ResultOp)); + r = new CalcStmt(Tok(s.Tok), Tok(s.EndTok), CloneCalcOp(s.Op), s.Lines.ConvertAll(CloneExpr), s.Hints.ConvertAll(CloneBlockStmt), s.StepOps.ConvertAll(CloneCalcOp), CloneCalcOp(s.ResultOp), CloneAttributes(s.Attributes)); } else if (stmt is MatchStmt) { var s = (MatchStmt)stmt; diff --git a/Source/Dafny/Dafny.atg b/Source/Dafny/Dafny.atg index 6cc0af5a..5d4a4321 100644 --- a/Source/Dafny/Dafny.atg +++ b/Source/Dafny/Dafny.atg @@ -1965,6 +1965,7 @@ ModifyStmt CalcStmt = (. Contract.Ensures(Contract.ValueAtReturn(out s) != null); Token x; + Attributes attrs = null; CalcStmt.CalcOp op, calcOp = Microsoft.Dafny.CalcStmt.DefaultOp, resOp = Microsoft.Dafny.CalcStmt.DefaultOp; var lines = new List(); var hints = new List(); @@ -1976,6 +1977,7 @@ CalcStmt IToken danglingOperator = null; .) "calc" (. x = t; .) + { IF(IsAttribute()) Attribute } [ CalcOp (. maybeOp = calcOp.ResultOp(calcOp); // guard against non-transitive calcOp (like !=) if (maybeOp == null) { SemErr(opTok, "the main operator of a calculation must be transitive"); @@ -2024,7 +2026,7 @@ CalcStmt // Repeat the last line to create a dummy line for the dangling hint lines.Add(lines[lines.Count - 1]); } - s = new CalcStmt(x, t, calcOp, lines, hints, stepOps, resOp); + s = new CalcStmt(x, t, calcOp, lines, hints, stepOps, resOp, attrs); .) . CalcOp diff --git a/Source/Dafny/DafnyAst.cs b/Source/Dafny/DafnyAst.cs index b8660f98..c9c9ccc8 100644 --- a/Source/Dafny/DafnyAst.cs +++ b/Source/Dafny/DafnyAst.cs @@ -314,6 +314,22 @@ namespace Microsoft.Dafny { return null; } + + /// + /// Same as FindExpressions, but returns all matches + /// + public static List> FindAllExpressions(Attributes attrs, string nm) { + Contract.Requires(nm != null); + List> ret = null; + for (; attrs != null; attrs = attrs.Prev) { + if (attrs.Name == nm) { + ret = ret ?? new List>(); // Avoid allocating the list in the common case where we don't find nm + ret.Add(attrs.Args); + } + } + return ret; + } + /// /// Returns true if "nm" is a specified attribute whose arguments match the "allowed" parameter. /// - if "nm" is not found in attrs, return false and leave value unmodified. Otherwise, @@ -2874,6 +2890,7 @@ namespace Microsoft.Dafny { public override string WhatKind { get { return "function"; } } public readonly bool IsProtected; public bool IsRecursive; // filled in during resolution + public bool IsFueled; // filled in during resolution if anyone tries to adjust this function's fuel public readonly List TypeArgs; public readonly List Formals; public readonly Type ResultType; @@ -2899,7 +2916,7 @@ namespace Microsoft.Dafny { return Contract.Exists(Decreases.Expressions, e => e is WildcardExpr); } } - + /// /// The "AllCalls" field is used for non-FixpointPredicate, non-PrefixPredicate functions only (so its value should not be relied upon for FixpointPredicate and PrefixPredicate functions). /// It records all function calls made by the Function, including calls made in the body as well as in the specification. @@ -2944,6 +2961,7 @@ namespace Microsoft.Dafny { Contract.Requires(cce.NonNullElements(ens)); Contract.Requires(decreases != null); this.IsProtected = isProtected; + this.IsFueled = false; // Defaults to false. Only set to true if someone mentions this function in a fuel annotation this.TypeArgs = typeArgs; this.Formals = formals; this.ResultType = resultType; @@ -2968,6 +2986,8 @@ namespace Microsoft.Dafny { } ModuleDefinition ICodeContext.EnclosingModule { get { return this.EnclosingClass.Module; } } bool ICodeContext.MustReverify { get { return false; } } + + public bool IsFuelAware() { return IsRecursive || IsFueled; } } public class Predicate : Function @@ -4640,7 +4660,7 @@ namespace Microsoft.Dafny { Contract.Invariant(StepOps.Count == Hints.Count); } - public CalcStmt(IToken tok, IToken endTok, CalcOp op, List lines, List hints, List stepOps, CalcOp resultOp) + public CalcStmt(IToken tok, IToken endTok, CalcOp op, List lines, List hints, List stepOps, CalcOp resultOp, Attributes attrs) : base(tok, endTok) { Contract.Requires(tok != null); @@ -4665,6 +4685,7 @@ namespace Microsoft.Dafny { } this.Steps = new List(); this.Result = null; + this.Attributes = attrs; } public override IEnumerable SubStatements diff --git a/Source/Dafny/Parser.cs b/Source/Dafny/Parser.cs index b183fff1..c4047819 100644 --- a/Source/Dafny/Parser.cs +++ b/Source/Dafny/Parser.cs @@ -74,8 +74,8 @@ public class Parser { public const int _ellipsis = 58; public const int maxT = 137; - const bool _T = true; - const bool _x = false; + const bool T = true; + const bool x = false; const int minErrDist = 2; public Scanner/*!*/ scanner; @@ -2565,6 +2565,7 @@ List/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo void CalcStmt(out Statement s) { Contract.Ensures(Contract.ValueAtReturn(out s) != null); Token x; + Attributes attrs = null; CalcStmt.CalcOp op, calcOp = Microsoft.Dafny.CalcStmt.DefaultOp, resOp = Microsoft.Dafny.CalcStmt.DefaultOp; var lines = new List(); var hints = new List(); @@ -2577,6 +2578,9 @@ List/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo Expect(31); x = t; + while (IsAttribute()) { + Attribute(ref attrs); + } if (StartOf(25)) { CalcOp(out opTok, out calcOp); maybeOp = calcOp.ResultOp(calcOp); // guard against non-transitive calcOp (like !=) @@ -2631,7 +2635,7 @@ List/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo // Repeat the last line to create a dummy line for the dangling hint lines.Add(lines[lines.Count - 1]); } - s = new CalcStmt(x, t, calcOp, lines, hints, stepOps, resOp); + s = new CalcStmt(x, t, calcOp, lines, hints, stepOps, resOp, attrs); } @@ -3988,7 +3992,7 @@ List/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo Get(); S = Util.RemoveUnderscores(t.val); try { - n = BigIntegerParser.Parse(S); + n = BigIntegerParser.Parse(S); } catch (System.FormatException) { SemErr("incorrectly formatted number"); n = BigInteger.Zero; @@ -3999,7 +4003,7 @@ List/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo S = Util.RemoveUnderscores(t.val.Substring(2)); try { // note: leading 0 required when parsing positive hex numbers - n = BigIntegerParser.Parse("0" + S, System.Globalization.NumberStyles.HexNumber); + n = BigIntegerParser.Parse("0" + S, System.Globalization.NumberStyles.HexNumber); } catch (System.FormatException) { SemErr("incorrectly formatted number"); n = BigInteger.Zero; @@ -4364,38 +4368,38 @@ List/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo } static readonly bool[,]/*!*/ set = { - {_T,_T,_T,_T, _T,_x,_x,_x, _T,_x,_T,_x, _x,_x,_x,_x, _x,_x,_x,_T, _T,_x,_x,_T, _x,_x,_x,_T, _x,_x,_T,_T, _T,_x,_x,_T, _T,_x,_x,_T, _T,_x,_T,_T, _T,_T,_T,_x, _x,_T,_x,_x, _x,_x,_x,_x, _x,_x,_T,_x, _x,_x,_x,_x, _x,_x,_x,_x, _T,_x,_T,_T, _x,_x,_T,_T, _T,_x,_x,_T, _x,_x,_T,_T, _T,_T,_T,_T, _T,_x,_T,_T, _x,_x,_T,_x, _x,_T,_T,_T, _T,_T,_T,_T, _T,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_T,_T, _T,_T,_T,_T, _x,_x,_x}, - {_x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_T,_T,_T, _T,_T,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _T,_T,_x,_T, _x,_x,_x,_x, _T,_x,_T,_T, _T,_T,_T,_T, _T,_T,_T,_T, _x,_x,_T,_T, _T,_T,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x}, - {_x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_T,_T,_T, _T,_T,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_T, _T,_T,_x,_x, _T,_x,_x,_x, _x,_x,_T,_T, _T,_T,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x}, - {_x,_T,_x,_x, _x,_T,_T,_T, _T,_T,_T,_T, _T,_T,_T,_T, _T,_T,_T,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_T,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x}, - {_T,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_T, _x,_x,_x,_x, _x,_x,_x,_x, _x,_T,_T,_T, _T,_T,_x,_x, _x,_x,_T,_x, _x,_x,_x,_T, _x,_x,_x,_x, _x,_x,_x,_x, _T,_T,_x,_T, _x,_T,_x,_x, _T,_x,_T,_T, _T,_T,_T,_T, _T,_T,_T,_T, _x,_x,_T,_T, _T,_T,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x}, - {_x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_T, _x,_x,_x,_x, _x,_x,_T,_T, _T,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_T,_T, _T,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x}, - {_x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_T, _T,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_T,_T, _T,_T,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x}, - {_x,_T,_T,_T, _T,_x,_x,_x, _T,_x,_T,_x, _x,_T,_T,_T, _x,_T,_T,_T, _T,_x,_x,_T, _x,_x,_x,_x, _x,_x,_T,_T, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_T,_x,_T, _x,_T,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_T, _x,_x,_x,_x, _T,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_T,_x, _x,_x,_x,_x, _x,_T,_x,_T, _T,_x,_T,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _T,_T,_T,_T, _T,_x,_x,_T, _x,_x,_T,_T, _T,_T,_T,_T, _x,_x,_x}, - {_T,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_T,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_T, _x,_T,_T,_T, _T,_T,_x,_T, _T,_T,_T,_x, _x,_T,_x,_T, _x,_x,_x,_x, _x,_x,_x,_x, _T,_T,_x,_T, _x,_x,_x,_x, _T,_x,_T,_T, _T,_T,_T,_T, _T,_T,_T,_T, _x,_x,_T,_T, _T,_T,_x,_T, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x}, - {_x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_T, _x,_x,_x,_x, _x,_x,_x,_T, _T,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_T, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x}, - {_T,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_T, _T,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_T,_T, _T,_T,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x}, - {_x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_T, _x,_x,_x,_x, _x,_x,_T,_x, _T,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_T,_T, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x}, - {_x,_T,_T,_x, _x,_T,_T,_T, _T,_T,_T,_T, _T,_T,_T,_T, _T,_T,_T,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_T,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_T, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x}, - {_T,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_T, _x,_x,_x,_x, _x,_x,_T,_T, _T,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_T,_T, _T,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x}, - {_x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _T,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_T,_T, _T,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x}, - {_x,_T,_T,_T, _T,_x,_x,_x, _T,_x,_T,_x, _x,_x,_x,_x, _x,_x,_x,_T, _T,_x,_x,_T, _x,_x,_x,_x, _x,_x,_T,_T, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_T,_x,_x, _x,_T,_x,_x, _x,_x,_x,_x, _x,_x,_T,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_T, _x,_x,_x,_x, _T,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _T,_x,_T,_T, _x,_x,_T,_x, _x,_T,_T,_T, _T,_T,_T,_T, _T,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_T,_T, _T,_T,_T,_T, _x,_x,_x}, - {_T,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_T, _x,_x,_x,_x, _x,_x,_T,_x, _T,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_T,_T, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x}, - {_T,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_T, _x,_x,_x,_x, _x,_x,_x,_T, _T,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_T, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x}, - {_x,_T,_T,_T, _T,_x,_x,_x, _T,_x,_T,_x, _x,_T,_T,_T, _x,_T,_T,_T, _T,_x,_x,_T, _x,_x,_x,_x, _x,_x,_T,_T, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_T,_x,_T, _x,_T,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_T, _x,_x,_x,_x, _T,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_T,_T,_x, _x,_x,_x,_x, _x,_T,_x,_T, _T,_x,_T,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _T,_T,_T,_T, _T,_x,_x,_T, _x,_x,_T,_T, _T,_T,_T,_T, _x,_x,_x}, - {_T,_T,_T,_T, _T,_x,_x,_x, _T,_x,_T,_x, _x,_x,_x,_x, _x,_x,_x,_T, _T,_x,_x,_T, _x,_x,_x,_x, _x,_x,_T,_T, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_T,_x,_x, _x,_T,_x,_x, _x,_x,_x,_x, _x,_x,_T,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_T, _x,_x,_x,_x, _T,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _T,_x,_T,_T, _x,_x,_T,_x, _x,_T,_T,_T, _T,_T,_T,_T, _T,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_T,_T, _T,_T,_T,_T, _x,_x,_x}, - {_x,_T,_T,_T, _T,_x,_x,_x, _T,_x,_T,_x, _x,_T,_T,_T, _x,_T,_T,_T, _T,_x,_x,_T, _x,_x,_x,_x, _x,_x,_T,_T, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_T,_x,_T, _x,_T,_x,_x, _x,_x,_x,_x, _T,_x,_T,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_T, _x,_x,_x,_x, _T,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_T,_x, _x,_x,_x,_x, _x,_T,_x,_T, _T,_x,_T,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _T,_T,_T,_T, _T,_x,_x,_T, _x,_x,_T,_T, _T,_T,_T,_T, _x,_x,_x}, - {_x,_T,_T,_T, _T,_x,_x,_x, _T,_x,_T,_x, _x,_T,_T,_T, _x,_T,_T,_T, _T,_x,_x,_T, _x,_x,_x,_x, _x,_x,_T,_T, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_T,_x,_T, _x,_T,_x,_x, _x,_x,_x,_x, _T,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_T, _x,_x,_x,_x, _T,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_T,_x, _x,_x,_x,_x, _x,_T,_x,_T, _T,_x,_T,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _T,_T,_T,_T, _T,_x,_x,_T, _x,_x,_T,_T, _T,_T,_T,_T, _x,_x,_x}, - {_x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_T, _T,_x,_x,_x, _x,_x,_T,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_T,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x}, - {_x,_T,_T,_T, _T,_x,_x,_x, _T,_x,_T,_x, _x,_x,_x,_x, _x,_x,_x,_T, _T,_x,_x,_T, _x,_x,_x,_x, _x,_x,_T,_T, _T,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_T,_T,_x, _x,_T,_x,_x, _x,_x,_x,_x, _x,_x,_T,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_T, _x,_x,_x,_x, _T,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _T,_x,_T,_T, _x,_x,_T,_x, _x,_T,_T,_T, _T,_T,_T,_T, _T,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_T,_T, _T,_T,_T,_T, _x,_x,_x}, - {_x,_T,_T,_T, _T,_x,_x,_x, _T,_x,_T,_x, _x,_x,_x,_x, _x,_x,_x,_T, _T,_x,_x,_T, _x,_x,_x,_x, _x,_x,_T,_T, _T,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_T,_T,_x, _x,_T,_x,_x, _x,_x,_x,_x, _x,_x,_T,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_T, _x,_x,_x,_x, _T,_x,_x,_x, _x,_x,_x,_x, _x,_x,_T,_T, _T,_x,_T,_T, _x,_x,_T,_x, _x,_T,_T,_T, _T,_T,_T,_T, _T,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_T,_T, _T,_T,_T,_T, _x,_x,_x}, - {_x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_T, _T,_T,_T,_T, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_T,_T, _T,_T,_T,_T, _T,_T,_T,_T, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x}, - {_x,_T,_T,_T, _T,_x,_x,_x, _T,_x,_T,_x, _x,_T,_T,_T, _x,_T,_T,_T, _T,_x,_x,_T, _x,_x,_x,_x, _x,_x,_T,_T, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_T,_x,_T, _x,_T,_x,_x, _x,_x,_x,_x, _T,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_T, _x,_x,_x,_x, _T,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_T,_x, _x,_x,_x,_x, _T,_T,_x,_T, _T,_x,_T,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _T,_T,_T,_T, _T,_x,_x,_T, _x,_x,_T,_T, _T,_T,_T,_T, _x,_x,_x}, - {_x,_x,_T,_T, _T,_x,_x,_x, _T,_x,_T,_x, _x,_x,_x,_x, _x,_x,_x,_T, _T,_x,_x,_T, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_T,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_T,_T, _T,_T,_T,_T, _x,_x,_x}, - {_T,_T,_T,_T, _T,_x,_x,_x, _T,_x,_T,_x, _x,_x,_x,_x, _x,_x,_x,_T, _T,_x,_x,_T, _x,_x,_x,_x, _x,_x,_T,_T, _T,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_T,_T,_x, _x,_T,_x,_x, _x,_x,_x,_x, _x,_x,_T,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_T, _x,_x,_x,_x, _T,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _T,_x,_T,_T, _x,_x,_T,_x, _x,_T,_T,_T, _T,_T,_T,_T, _T,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_T,_T, _T,_T,_T,_T, _x,_x,_x}, - {_x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_T,_T,_x, _x,_T,_T,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_T,_T, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_T, _x,_x,_x,_x, _T,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_T,_x, _x,_x,_x,_x, _x,_T,_x,_T, _T,_x,_T,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_T,_T, _T,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x}, - {_T,_T,_T,_T, _T,_x,_x,_x, _T,_x,_T,_x, _x,_x,_x,_x, _x,_x,_x,_T, _T,_T,_T,_T, _T,_T,_T,_T, _T,_T,_T,_T, _T,_T,_T,_T, _T,_T,_T,_T, _T,_T,_T,_T, _T,_T,_T,_T, _T,_T,_T,_T, _T,_T,_T,_T, _T,_T,_T,_x, _T,_T,_x,_T, _x,_x,_x,_x, _T,_x,_T,_T, _T,_T,_T,_T, _T,_T,_T,_T, _x,_x,_T,_T, _T,_T,_T,_T, _T,_T,_T,_T, _x,_T,_T,_T, _x,_T,_T,_T, _T,_T,_T,_T, _T,_x,_T,_T, _T,_T,_T,_T, _T,_T,_T,_T, _T,_T,_T,_T, _T,_x,_x,_x, _x,_T,_T,_T, _T,_T,_T,_T, _T,_T,_T,_T, _T,_x,_x}, - {_T,_T,_T,_T, _T,_x,_x,_x, _T,_x,_T,_x, _x,_x,_x,_x, _x,_x,_x,_T, _T,_T,_T,_T, _T,_T,_x,_T, _T,_T,_T,_T, _T,_T,_T,_T, _T,_T,_T,_T, _T,_T,_T,_T, _T,_T,_T,_x, _T,_T,_T,_T, _T,_T,_T,_T, _T,_T,_T,_x, _T,_T,_x,_T, _x,_x,_x,_x, _T,_x,_T,_T, _T,_T,_T,_T, _T,_T,_T,_T, _x,_x,_T,_T, _T,_T,_T,_T, _T,_T,_T,_T, _x,_T,_T,_x, _x,_T,_T,_T, _T,_T,_T,_T, _T,_x,_T,_T, _T,_T,_T,_T, _T,_T,_T,_T, _T,_T,_T,_T, _T,_x,_x,_x, _x,_T,_T,_T, _T,_T,_T,_T, _T,_T,_T,_T, _T,_x,_x} + {T,T,T,T, T,x,x,x, T,x,T,x, x,x,x,x, x,x,x,T, T,x,x,T, x,x,x,T, x,x,T,T, T,x,x,T, T,x,x,T, T,x,T,T, T,T,T,x, x,T,x,x, x,x,x,x, x,x,T,x, x,x,x,x, x,x,x,x, T,x,T,T, x,x,T,T, T,x,x,T, x,x,T,T, T,T,T,T, T,x,T,T, x,x,T,x, x,T,T,T, T,T,T,T, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,T,T, T,T,T,T, x,x,x}, + {x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,T,T,T, T,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, T,T,x,T, x,x,x,x, T,x,T,T, T,T,T,T, T,T,T,T, x,x,T,T, T,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x}, + {x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,T,T,T, T,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,T, T,T,x,x, T,x,x,x, x,x,T,T, T,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x}, + {x,T,x,x, x,T,T,T, T,T,T,T, T,T,T,T, T,T,T,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x}, + {T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,T, x,x,x,x, x,x,x,x, x,T,T,T, T,T,x,x, x,x,T,x, x,x,x,T, x,x,x,x, x,x,x,x, T,T,x,T, x,T,x,x, T,x,T,T, T,T,T,T, T,T,T,T, x,x,T,T, T,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x}, + {x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,T, x,x,x,x, x,x,T,T, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,T,T, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x}, + {x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,T, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,T,T, T,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x}, + {x,T,T,T, T,x,x,x, T,x,T,x, x,T,T,T, x,T,T,T, T,x,x,T, x,x,x,x, x,x,T,T, x,x,x,x, x,x,x,x, x,x,x,x, x,T,x,T, x,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,T, x,x,x,x, T,x,x,x, x,x,x,x, x,x,x,x, x,x,T,x, x,x,x,x, x,T,x,T, T,x,T,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, T,T,T,T, T,x,x,T, x,x,T,T, T,T,T,T, x,x,x}, + {T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,T,x,x, x,x,x,x, x,x,x,x, x,x,x,T, x,T,T,T, T,T,x,T, T,T,T,x, x,T,x,T, x,x,x,x, x,x,x,x, T,T,x,T, x,x,x,x, T,x,T,T, T,T,T,T, T,T,T,T, x,x,T,T, T,T,x,T, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x}, + {x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,T, x,x,x,x, x,x,x,T, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,T, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x}, + {T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,T, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,T,T, T,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x}, + {x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,T, x,x,x,x, x,x,T,x, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,T,T, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x}, + {x,T,T,x, x,T,T,T, T,T,T,T, T,T,T,T, T,T,T,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,T, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x}, + {T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,T, x,x,x,x, x,x,T,T, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,T,T, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x}, + {x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,T,T, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x}, + {x,T,T,T, T,x,x,x, T,x,T,x, x,x,x,x, x,x,x,T, T,x,x,T, x,x,x,x, x,x,T,T, x,x,x,x, x,x,x,x, x,x,x,x, x,T,x,x, x,T,x,x, x,x,x,x, x,x,T,x, x,x,x,x, x,x,x,x, x,x,x,T, x,x,x,x, T,x,x,x, x,x,x,x, x,x,x,x, T,x,T,T, x,x,T,x, x,T,T,T, T,T,T,T, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,T,T, T,T,T,T, x,x,x}, + {T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,T, x,x,x,x, x,x,T,x, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,T,T, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x}, + {T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,T, x,x,x,x, x,x,x,T, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,T, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x}, + {x,T,T,T, T,x,x,x, T,x,T,x, x,T,T,T, x,T,T,T, T,x,x,T, x,x,x,x, x,x,T,T, x,x,x,x, x,x,x,x, x,x,x,x, x,T,x,T, x,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,T, x,x,x,x, T,x,x,x, x,x,x,x, x,x,x,x, x,T,T,x, x,x,x,x, x,T,x,T, T,x,T,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, T,T,T,T, T,x,x,T, x,x,T,T, T,T,T,T, x,x,x}, + {T,T,T,T, T,x,x,x, T,x,T,x, x,x,x,x, x,x,x,T, T,x,x,T, x,x,x,x, x,x,T,T, x,x,x,x, x,x,x,x, x,x,x,x, x,T,x,x, x,T,x,x, x,x,x,x, x,x,T,x, x,x,x,x, x,x,x,x, x,x,x,T, x,x,x,x, T,x,x,x, x,x,x,x, x,x,x,x, T,x,T,T, x,x,T,x, x,T,T,T, T,T,T,T, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,T,T, T,T,T,T, x,x,x}, + {x,T,T,T, T,x,x,x, T,x,T,x, x,T,T,T, x,T,T,T, T,x,x,T, x,x,x,x, x,x,T,T, x,x,x,x, x,x,x,x, x,x,x,x, x,T,x,T, x,T,x,x, x,x,x,x, T,x,T,x, x,x,x,x, x,x,x,x, x,x,x,T, x,x,x,x, T,x,x,x, x,x,x,x, x,x,x,x, x,x,T,x, x,x,x,x, x,T,x,T, T,x,T,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, T,T,T,T, T,x,x,T, x,x,T,T, T,T,T,T, x,x,x}, + {x,T,T,T, T,x,x,x, T,x,T,x, x,T,T,T, x,T,T,T, T,x,x,T, x,x,x,x, x,x,T,T, x,x,x,x, x,x,x,x, x,x,x,x, x,T,x,T, x,T,x,x, x,x,x,x, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,T, x,x,x,x, T,x,x,x, x,x,x,x, x,x,x,x, x,x,T,x, x,x,x,x, x,T,x,T, T,x,T,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, T,T,T,T, T,x,x,T, x,x,T,T, T,T,T,T, x,x,x}, + {x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,T, T,x,x,x, x,x,T,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,T,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x}, + {x,T,T,T, T,x,x,x, T,x,T,x, x,x,x,x, x,x,x,T, T,x,x,T, x,x,x,x, x,x,T,T, T,x,x,x, x,x,x,x, x,x,x,x, x,T,T,x, x,T,x,x, x,x,x,x, x,x,T,x, x,x,x,x, x,x,x,x, x,x,x,T, x,x,x,x, T,x,x,x, x,x,x,x, x,x,x,x, T,x,T,T, x,x,T,x, x,T,T,T, T,T,T,T, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,T,T, T,T,T,T, x,x,x}, + {x,T,T,T, T,x,x,x, T,x,T,x, x,x,x,x, x,x,x,T, T,x,x,T, x,x,x,x, x,x,T,T, T,x,x,x, x,x,x,x, x,x,x,x, x,T,T,x, x,T,x,x, x,x,x,x, x,x,T,x, x,x,x,x, x,x,x,x, x,x,x,T, x,x,x,x, T,x,x,x, x,x,x,x, x,x,T,T, T,x,T,T, x,x,T,x, x,T,T,T, T,T,T,T, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,T,T, T,T,T,T, x,x,x}, + {x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,T, T,T,T,T, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,T,T, T,T,T,T, T,T,T,T, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x}, + {x,T,T,T, T,x,x,x, T,x,T,x, x,T,T,T, x,T,T,T, T,x,x,T, x,x,x,x, x,x,T,T, x,x,x,x, x,x,x,x, x,x,x,x, x,T,x,T, x,T,x,x, x,x,x,x, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,T, x,x,x,x, T,x,x,x, x,x,x,x, x,x,x,x, x,x,T,x, x,x,x,x, T,T,x,T, T,x,T,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, T,T,T,T, T,x,x,T, x,x,T,T, T,T,T,T, x,x,x}, + {x,x,T,T, T,x,x,x, T,x,T,x, x,x,x,x, x,x,x,T, T,x,x,T, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,T,T, T,T,T,T, x,x,x}, + {T,T,T,T, T,x,x,x, T,x,T,x, x,x,x,x, x,x,x,T, T,x,x,T, x,x,x,x, x,x,T,T, T,x,x,x, x,x,x,x, x,x,x,x, x,T,T,x, x,T,x,x, x,x,x,x, x,x,T,x, x,x,x,x, x,x,x,x, x,x,x,T, x,x,x,x, T,x,x,x, x,x,x,x, x,x,x,x, T,x,T,T, x,x,T,x, x,T,T,T, T,T,T,T, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,T,T, T,T,T,T, x,x,x}, + {x,x,x,x, x,x,x,x, x,x,x,x, x,T,T,x, x,T,T,x, x,x,x,x, x,x,x,x, x,x,T,T, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,T, x,x,x,x, T,x,x,x, x,x,x,x, x,x,x,x, x,x,T,x, x,x,x,x, x,T,x,T, T,x,T,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,T,T, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x}, + {T,T,T,T, T,x,x,x, T,x,T,x, x,x,x,x, x,x,x,T, T,T,T,T, T,T,T,T, T,T,T,T, T,T,T,T, T,T,T,T, T,T,T,T, T,T,T,T, T,T,T,T, T,T,T,T, T,T,T,x, T,T,x,T, x,x,x,x, T,x,T,T, T,T,T,T, T,T,T,T, x,x,T,T, T,T,T,T, T,T,T,T, x,T,T,T, x,T,T,T, T,T,T,T, T,x,T,T, T,T,T,T, T,T,T,T, T,T,T,T, T,x,x,x, x,T,T,T, T,T,T,T, T,T,T,T, T,x,x}, + {T,T,T,T, T,x,x,x, T,x,T,x, x,x,x,x, x,x,x,T, T,T,T,T, T,T,x,T, T,T,T,T, T,T,T,T, T,T,T,T, T,T,T,T, T,T,T,x, T,T,T,T, T,T,T,T, T,T,T,x, T,T,x,T, x,x,x,x, T,x,T,T, T,T,T,T, T,T,T,T, x,x,T,T, T,T,T,T, T,T,T,T, x,T,T,x, x,T,T,T, T,T,T,T, T,x,T,T, T,T,T,T, T,T,T,T, T,T,T,T, T,x,x,x, x,T,T,T, T,T,T,T, T,T,T,T, T,x,x} }; } // end Parser diff --git a/Source/Dafny/Resolver.cs b/Source/Dafny/Resolver.cs index 835871d9..e48a7932 100644 --- a/Source/Dafny/Resolver.cs +++ b/Source/Dafny/Resolver.cs @@ -455,6 +455,25 @@ 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); + 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); + } else if (clbl is IteratorDecl) { + body = ((IteratorDecl)clbl).Body; + CheckForFuelAdjustments(clbl.Tok, ((IteratorDecl)clbl).Attributes, module, this); + } + if (body != null) { + var c = new FuelAdjustment_Visitor(this); + c.Visit(body, new FuelAdjustment_Context(module, this)); + } + } + } } void FillInDefaultDecreasesClauses(Program prog) @@ -683,8 +702,8 @@ namespace Microsoft.Dafny var datatypeDependencies = new Graph(); var codatatypeDependencies = new Graph(); int prevErrorCount = ErrorCount; - ResolveAttributes(m.Attributes, new ResolveOpts(new NoContext(m.Module), false)); 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); } @@ -2335,6 +2354,59 @@ namespace Microsoft.Dafny } #endregion CheckTailRecursive + // ------------------------------------------------------------------------------------------------------ + // ----- FuelAdjustmentChecks --------------------------------------------------------------------------- + // ------------------------------------------------------------------------------------------------------ + #region FuelAdjustmentChecks + + protected static void CheckForFuelAdjustments(IToken tok, Attributes attrs, ModuleDefinition currentModule, ResolutionErrorReporter reporter) { + List> results = Attributes.FindAllExpressions(attrs, "fuel"); + + if (results != null) { + foreach (List args in results) { + if (args != null && args.Count >= 2) { + // Try to extract the function from the first argument + MemberSelectExpr selectExpr = args[0].Resolved as MemberSelectExpr; + if (selectExpr != null) { + Function f = selectExpr.Member as Function; + 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); + } + } + } + } + } + } + } + + public class FuelAdjustment_Context + { + public ModuleDefinition currentModule; + public ResolutionErrorReporter reporter; + public FuelAdjustment_Context(ModuleDefinition currentModule, ResolutionErrorReporter reporter) { + this.currentModule = currentModule; + this.reporter = reporter; + } + } + + class FuelAdjustment_Visitor : ResolverTopDownVisitor + { + public FuelAdjustment_Visitor(Resolver resolver) + : base(resolver) { + Contract.Requires(resolver != null); + } + + protected override bool VisitOneStmt(Statement stmt, ref FuelAdjustment_Context st) { + Contract.Requires(stmt != null); + Resolver.CheckForFuelAdjustments(stmt.Tok, stmt.Attributes, st.currentModule, st.reporter); + return true; + } + } + + #endregion FuelAdjustmentChecks + // ------------------------------------------------------------------------------------------------------ // ----- FixpointPredicateChecks ------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------------ diff --git a/Source/Dafny/Scanner.cs b/Source/Dafny/Scanner.cs index 4c5eedb4..d0d2e4dd 100644 --- a/Source/Dafny/Scanner.cs +++ b/Source/Dafny/Scanner.cs @@ -217,7 +217,7 @@ public class Scanner { [ContractInvariantMethod] void objectInvariant(){ - Contract.Invariant(this._buffer != null); + Contract.Invariant(buffer!=null); Contract.Invariant(t != null); Contract.Invariant(start != null); Contract.Invariant(tokens != null); @@ -227,18 +227,7 @@ public class Scanner { Contract.Invariant(errorHandler != null); } - private Buffer/*!*/ _buffer; // scanner buffer - - public Buffer/*!*/ buffer { - get { - Contract.Ensures(Contract.Result() != null); - return this._buffer; - } - set { - Contract.Requires(value != null); - this._buffer = value; - } - } + public Buffer/*!*/ buffer; // scanner buffer Token/*!*/ t; // current token int ch; // current input character @@ -310,7 +299,7 @@ public class Scanner { } // [NotDelayed] - public Scanner (string/*!*/ fileName, Errors/*!*/ errorHandler, bool useBaseName = false) : base() { + public Scanner (string/*!*/ fileName, Errors/*!*/ errorHandler) : base() { Contract.Requires(fileName != null); Contract.Requires(errorHandler != null); this.errorHandler = errorHandler; @@ -318,8 +307,8 @@ public class Scanner { t = new Token(); // dummy because t is a non-null field try { Stream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read); - this._buffer = new Buffer(stream, false); - Filename = useBaseName? GetBaseName(fileName): fileName; + buffer = new Buffer(stream, false); + Filename = fileName; Init(); } catch (IOException) { throw new FatalError("Cannot open file " + fileName); @@ -327,22 +316,18 @@ public class Scanner { } // [NotDelayed] - public Scanner (Stream/*!*/ s, Errors/*!*/ errorHandler, string/*!*/ fileName, bool useBaseName = false) : base() { + public Scanner (Stream/*!*/ s, Errors/*!*/ errorHandler, string/*!*/ fileName) : base() { 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); + buffer = new Buffer(s, true); this.errorHandler = errorHandler; - this.Filename = useBaseName? GetBaseName(fileName) : fileName; + this.Filename = fileName; Init(); } - string GetBaseName(string fileName) { - return System.IO.Path.GetFileName(fileName); // Return basename - } - void Init() { pos = -1; line = 1; col = 0; oldEols = 0; diff --git a/Source/Dafny/Translator.cs b/Source/Dafny/Translator.cs index 4324b2b8..9ba11e2f 100644 --- a/Source/Dafny/Translator.cs +++ b/Source/Dafny/Translator.cs @@ -114,6 +114,7 @@ namespace Microsoft.Dafny { readonly Dictionary fieldConstants = new Dictionary(); readonly ISet abstractTypes = new HashSet(); readonly ISet opaqueTypes = new HashSet(); + FuelContext fuelContext = null; Program program; [ContractInvariantMethod] @@ -625,6 +626,11 @@ namespace Microsoft.Dafny { } void AddTypeDecl(NewtypeDecl dd) { Contract.Requires(dd != null); + Contract.Ensures(fuelContext == Contract.OldValue(fuelContext)); + + FuelContext oldFuelContext = this.fuelContext; + this.fuelContext = FuelSetting.NewFuelContext(dd); + AddTypeDecl_Aux(dd.tok, dd.FullName, new List()); AddWellformednessCheck(dd); // Add $Is and $IsAlloc axioms for the newtype @@ -667,6 +673,7 @@ namespace Microsoft.Dafny { sink.AddTopLevelDeclaration(new Bpl.Axiom(dd.tok, BplForall(vars, BplTrigger(is_o), body), name)); }); + this.fuelContext = oldFuelContext; } void AddTypeDecl_Aux(IToken tok, string nm, List typeArgs) { Contract.Requires(tok != null); @@ -1181,7 +1188,7 @@ namespace Microsoft.Dafny { } } - Bpl.Expr LayerSucc(Bpl.Expr e, int amt = 1) { + public Bpl.Expr LayerSucc(Bpl.Expr e, int amt = 1) { if (amt == 0) { return e; } else if (amt > 0) { @@ -1301,6 +1308,7 @@ namespace Microsoft.Dafny { { Contract.Requires(sink != null && predef != null); Contract.Requires(c != null); + Contract.Ensures(fuelContext == Contract.OldValue(fuelContext)); sink.AddTopLevelDeclaration(GetClass(c)); if (c is ArrayClassDecl) { @@ -1387,6 +1395,9 @@ namespace Microsoft.Dafny { } else if (member is Function) { var f = (Function)member; + FuelContext oldFuelContext = this.fuelContext; + this.fuelContext = FuelSetting.NewFuelContext(f); + AddClassMember_Function(f); if (!IsOpaqueFunction(f) && !f.IsBuiltin && !(f.tok is IncludeToken)) { // Opaque function's well-formedness is checked on the full version AddWellformednessCheck(f); @@ -1399,9 +1410,11 @@ namespace Microsoft.Dafny { AddClassMember_Function(cop.PrefixPredicate); // skip the well-formedness check, because it has already been done for the fixpoint-predicate } - + this.fuelContext = oldFuelContext; } else if (member is Method) { Method m = (Method)member; + FuelContext oldFuelContext = this.fuelContext; + this.fuelContext = FuelSetting.NewFuelContext(m); // wellformedness check for method specification if (m.EnclosingClass is IteratorDecl && m == ((IteratorDecl)m.EnclosingClass).Member_MoveNext) { @@ -1434,7 +1447,7 @@ namespace Microsoft.Dafny { sink.AddTopLevelDeclaration(proc); AddMethodImpl(m, proc, false); } - + this.fuelContext = oldFuelContext; } else { Contract.Assert(false); throw new cce.UnreachableException(); // unexpected member } @@ -1467,7 +1480,7 @@ namespace Microsoft.Dafny { // declare function AddFunction(f); // add synonym axiom - if (f.IsRecursive) { + if (f.IsFuelAware()) { AddSynonymAxiom(f); } // add frame axiom @@ -1494,6 +1507,10 @@ namespace Microsoft.Dafny { void AddIteratorSpecAndBody(IteratorDecl iter) { Contract.Requires(iter != null); + Contract.Ensures(fuelContext == Contract.OldValue(fuelContext)); + + FuelContext oldFuelContext = this.fuelContext; + this.fuelContext = FuelSetting.NewFuelContext(iter); // wellformedness check for method specification Bpl.Procedure proc = AddIteratorProc(iter, MethodTranslationKind.SpecWellformedness); @@ -1506,6 +1523,7 @@ namespace Microsoft.Dafny { // ...and its implementation AddIteratorImpl(iter, proc); } + this.fuelContext = oldFuelContext; } Bpl.Procedure AddIteratorProc(IteratorDecl iter, MethodTranslationKind kind) { @@ -1950,7 +1968,7 @@ namespace Microsoft.Dafny { var formals = MkTyParamBinders(GetTypeParams(f), out tyargs); var args = new List(); Bpl.BoundVariable layer; - if (f.IsRecursive) { + if (f.IsFuelAware()) { layer = new Bpl.BoundVariable(f.tok, new Bpl.TypedIdent(f.tok, "$ly", predef.LayerType)); formals.Add(layer); // Note, "layer" is not added to "args" here; rather, that's done below, as needed @@ -2121,7 +2139,7 @@ namespace Microsoft.Dafny { var formals = MkTyParamBinders(GetTypeParams(f), out tyargs); Bpl.BoundVariable layer; - if (f.IsRecursive) { + if (f.IsFuelAware()) { layer = new Bpl.BoundVariable(f.tok, new Bpl.TypedIdent(f.tok, "$ly", predef.LayerType)); formals.Add(layer); // Note, "layer" is not added to "args" here; rather, that's done below, as needed @@ -2317,7 +2335,7 @@ namespace Microsoft.Dafny { void AddSynonymAxiom(Function f) { Contract.Requires(f != null); - Contract.Requires(f.IsRecursive); + Contract.Requires(f.IsFuelAware()); Contract.Requires(sink != null && predef != null); // axiom // layer synonym axiom // (forall s, $Heap, formals :: @@ -2400,7 +2418,7 @@ namespace Microsoft.Dafny { var coArgs = new List(tyexprs); var prefixArgs = new List(tyexprs); var prefixArgsLimited = new List(tyexprs); - if (pp.IsRecursive) { + if (pp.IsFuelAware()) { var sV = new Bpl.BoundVariable(tok, new Bpl.TypedIdent(tok, "$ly", predef.LayerType)); var s = new Bpl.IdentifierExpr(tok, sV); var succS = FunctionCall(tok, BuiltinFunction.LayerSucc, null, s); @@ -3073,13 +3091,13 @@ namespace Microsoft.Dafny { Bpl.FunctionCall funcIdT = new Bpl.FunctionCall(new Bpl.IdentifierExpr(f.OverriddenFunction.tok, f.OverriddenFunction.FullSanitizedName, TrType(f.OverriddenFunction.ResultType))); List argsC = new List(); List argsT = new List(); - if (f.IsRecursive) + if (f.IsFuelAware()) { - argsC.Add(etran.LayerN(1)); + argsC.Add(etran.layerInterCluster.GetFunctionFuel(f)); } - if (f.OverriddenFunction.IsRecursive) + if (f.OverriddenFunction.IsFuelAware()) { - argsT.Add(etran.LayerN(1)); + argsT.Add(etran.layerInterCluster.GetFunctionFuel(f)); } argsC.Add(etran.HeapExpr); argsT.Add(etran.HeapExpr); @@ -3726,7 +3744,7 @@ namespace Microsoft.Dafny { var typeParams = TrTypeParamDecls(f.TypeArgs); { var formals = new List(); - if (f.IsRecursive) { + if (f.IsFuelAware()) { formals.Add(new Bpl.Formal(f.tok, new Bpl.TypedIdent(f.tok, "$ly", predef.LayerType), true)); } if (!f.IsStatic) { @@ -3750,7 +3768,7 @@ namespace Microsoft.Dafny { List argsF = new List(); List argsFFrame = new List(); List argsCanCall = new List(); - if (f.IsRecursive) { + if (f.IsFuelAware()) { var sV = new Bpl.BoundVariable(f.tok, new Bpl.TypedIdent(f.tok, "$ly", predef.LayerType)); var s = new Bpl.IdentifierExpr(f.tok, sV); bvars.Add(sV); @@ -3795,7 +3813,7 @@ namespace Microsoft.Dafny { sink.AddTopLevelDeclaration(new Bpl.Axiom(f.tok, ax)); } else { #else - // This is the general case + // This is the general case Bpl.Expr h0; var h0Var = BplBoundVar("$h0", predef.HeapType, out h0); Bpl.Expr h1; var h1Var = BplBoundVar("$h1", predef.HeapType, out h1); @@ -3825,7 +3843,7 @@ namespace Microsoft.Dafny { var f1args = new List(tyexprs); var f0argsCanCall = new List(tyexprs); var f1argsCanCall = new List(tyexprs); - if (f.IsRecursive) { + if (f.IsFuelAware()) { Bpl.Expr s; var sV = BplBoundVar("$ly", predef.LayerType, out s); bvars.Add(sV); f0args.Add(s); f1args.Add(s); // but don't add to f0argsCanCall or f1argsCanCall @@ -4066,8 +4084,8 @@ namespace Microsoft.Dafny { foreach (var p in GetTypeParams(f)) { args.Add(trTypeParam(p, null)); } - if (f.IsRecursive) { - args.Add(etran.LayerN(1)); + if (f.IsFuelAware()) { + args.Add(etran.layerInterCluster.GetFunctionFuel(f)); } args.Add(etran.HeapExpr); if (!f.IsStatic) { @@ -4100,8 +4118,8 @@ namespace Microsoft.Dafny { foreach (var p in GetTypeParams(f)) { args.Add(trTypeParam(p, null)); } - if (f.IsRecursive) { - args.Add(etran.LayerN(1)); + if (f.IsFuelAware()) { + args.Add(etran.layerInterCluster.GetFunctionFuel(f)); } args.Add(etran.HeapExpr); foreach (Variable p in implInParams) { @@ -5572,7 +5590,7 @@ namespace Microsoft.Dafny { tyargs.Add(TypeToTy(fm.Type)); } tyargs.Add(TypeToTy(f.ResultType)); - if (f.IsRecursive) { + if (f.IsFuelAware()) { Bpl.Expr ly; vars.Add(BplBoundVar("$ly", predef.LayerType, out ly)); args.Add(ly); formals.Add(BplFormalVar(null, predef.LayerType, true)); } @@ -6135,7 +6153,7 @@ namespace Microsoft.Dafny { var typeParams = TrTypeParamDecls(f.TypeArgs); var formals = new List(); formals.AddRange(MkTyParamFormals(GetTypeParams(f))); - if (f.IsRecursive) { + if (f.IsFuelAware()) { formals.Add(new Bpl.Formal(f.tok, new Bpl.TypedIdent(f.tok, "$ly", predef.LayerType), true)); } formals.Add(new Bpl.Formal(f.tok, new Bpl.TypedIdent(f.tok, "$heap", predef.HeapType), true)); @@ -6212,7 +6230,7 @@ namespace Microsoft.Dafny { Contract.Requires(predef != null); Contract.Requires(currentModule == null && codeContext == null); Contract.Ensures(currentModule == null && codeContext == null); - Contract.Ensures(Contract.Result() != null); + Contract.Ensures(Contract.Result() != null); currentModule = m.EnclosingClass.Module; codeContext = m; @@ -6495,7 +6513,7 @@ namespace Microsoft.Dafny { // parameters of the procedure List inParams = new List(); Bpl.Formal layer; - if (f.IsRecursive) { + if (f.IsFuelAware()) { layer = new Bpl.Formal(f.tok, new Bpl.TypedIdent(f.tok, "$ly", predef.LayerType), true); inParams.Add(layer); } else { @@ -7018,9 +7036,11 @@ namespace Microsoft.Dafny { Contract.Requires(locals != null); Contract.Requires(etran != null); Contract.Requires(codeContext != null && predef != null); + Contract.Ensures(fuelContext == Contract.OldValue(fuelContext)); if (stmt is PredicateStmt) { + this.fuelContext = FuelSetting.ExpandFuelContext(stmt.Attributes, this.fuelContext); if (stmt is AssertStmt || DafnyOptions.O.DisallowSoundnessCheating) { - AddComment(builder, stmt, "assert statement"); + AddComment(builder, stmt, "assert statement"); PredicateStmt s = (PredicateStmt)stmt; TrStmt_CheckWellformed(s.Expr, builder, locals, etran, false); IToken enclosingToken = null; @@ -7040,13 +7060,14 @@ namespace Microsoft.Dafny { } } builder.Add(new Bpl.AssumeCmd(stmt.Tok, etran.TrExpr(s.Expr))); - } + } } else if (stmt is AssumeStmt) { AddComment(builder, stmt, "assume statement"); AssumeStmt s = (AssumeStmt)stmt; TrStmt_CheckWellformed(s.Expr, builder, locals, etran, false); builder.Add(new Bpl.AssumeCmd(stmt.Tok, etran.TrExpr(s.Expr), etran.TrAttributes(stmt.Attributes, null))); } + this.fuelContext = FuelSetting.PopFuelContext(); } else if (stmt is PrintStmt) { AddComment(builder, stmt, "print statement"); PrintStmt s = (PrintStmt)stmt; @@ -7279,6 +7300,7 @@ namespace Microsoft.Dafny { } else if (stmt is WhileStmt) { AddComment(builder, stmt, "while statement"); + this.fuelContext = FuelSetting.ExpandFuelContext(stmt.Attributes, this.fuelContext); var s = (WhileStmt)stmt; BodyTranslator bodyTr = null; if (s.Body != null) { @@ -7289,7 +7311,7 @@ namespace Microsoft.Dafny { }; } TrLoop(s, s.Guard, bodyTr, builder, locals, etran); - + this.fuelContext = FuelSetting.PopFuelContext(); } else if (stmt is AlternativeLoopStmt) { AddComment(builder, stmt, "alternative loop statement"); var s = (AlternativeLoopStmt)stmt; @@ -7331,6 +7353,7 @@ namespace Microsoft.Dafny { } else if (stmt is ForallStmt) { var s = (ForallStmt)stmt; + this.fuelContext = FuelSetting.ExpandFuelContext(stmt.Attributes, this.fuelContext); if (s.Kind == ForallStmt.ParBodyKind.Assign) { AddComment(builder, stmt, "forall statement (assign)"); Contract.Assert(s.Ens.Count == 0); @@ -7374,7 +7397,7 @@ namespace Microsoft.Dafny { } else { Contract.Assert(false); // unexpected kind } - + this.fuelContext = FuelSetting.PopFuelContext(); } else if (stmt is CalcStmt) { /* Translate into: if (*) { @@ -7397,9 +7420,10 @@ namespace Microsoft.Dafny { } assume line<0> op line; */ - var s = (CalcStmt)stmt; + var s = (CalcStmt)stmt; Contract.Assert(s.Steps.Count == s.Hints.Count); // established by the resolver AddComment(builder, stmt, "calc statement"); + this.fuelContext = FuelSetting.ExpandFuelContext(stmt.Attributes, this.fuelContext); CurrentIdGenerator.Push(); // put the entire calc statement within its own sub-branch if (s.Lines.Count > 0) { Bpl.IfCmd ifCmd = null; @@ -7464,7 +7488,7 @@ namespace Microsoft.Dafny { } } CurrentIdGenerator.Pop(); - + this.fuelContext = FuelSetting.PopFuelContext(); } else if (stmt is MatchStmt) { var s = (MatchStmt)stmt; TrStmt_CheckWellformed(s.Source, builder, locals, etran, true); @@ -10262,6 +10286,227 @@ namespace Microsoft.Dafny { } } + internal class FuelSettingPair + { + public int low; + public int high; + + public FuelSettingPair(int low = (int)FuelSetting.FuelAmount.LOW, int high = (int)FuelSetting.FuelAmount.HIGH) { + this.low = low; + this.high = high; + } + } + + // C#'s version of a type alias + internal class FuelContext : Dictionary { } + + internal class FuelSetting + { + public enum FuelAmount { NONE, LOW, HIGH }; + public static Stack SavedContexts = new Stack(); + + private static FuelSettingPair FuelAttrib(Function f) { + Contract.Requires(f != null); + Contract.Ensures(Contract.Result() != null); + FuelSettingPair setting = new FuelSettingPair(); + + if (f.Attributes != null) { + List args = Attributes.FindExpressions(f.Attributes, "fuel"); + if (args != null && args.Count >= 2) { + LiteralExpr literalLow = args[0] as LiteralExpr; + LiteralExpr literalHigh = args[1] as LiteralExpr; + + if (literalLow != null && literalLow.Value is BigInteger && literalHigh != null && literalHigh.Value is BigInteger) { + setting.low = (int)((BigInteger)literalLow.Value); + setting.high = (int)((BigInteger)literalHigh.Value); + } + } else if (args != null && args.Count >= 1) { + LiteralExpr literal = args[0] as LiteralExpr; + if (literal != null && literal.Value is BigInteger) { + setting.low = (int)((BigInteger)literal.Value); + setting.high = setting.low + 1; + } + } + } + + return setting; + } + + public int amount; // Amount of fuel above that represented by start + private Bpl.Expr start; // Starting fuel argument (null indicates LZ) + private Translator translator; + + public FuelSetting(Translator translator, int amount, Bpl.Expr start = null) { + this.translator = translator; + this.amount = amount; + this.start = start; + } + + public FuelSetting Offset(int offset) { + return new FuelSetting(translator, this.amount + offset, start); + } + + public Bpl.Expr LayerZero() { + Contract.Ensures(Contract.Result() != null); + return new Bpl.IdentifierExpr(Token.NoToken, "$LZ", translator.predef.LayerType); + } + + public Bpl.Expr LayerN(int n) { + Contract.Requires(0 <= n); + Contract.Ensures(Contract.Result() != null); + return translator.LayerSucc(LayerZero(), n); + } + + private Bpl.Expr ToExpr(int amount) { + if (start == null) { + return LayerN(amount); + } else { + return translator.LayerSucc(start, amount); + } + } + + public Bpl.Expr ToExpr() { + return this.ToExpr(this.amount); + } + + /// + /// Get the fuel value for this function, given the ambient environment (represented by the fuel setting) + /// the function itself, and the function call's context (if any) + /// + public Bpl.Expr GetFunctionFuel(Function f) { + Contract.Requires(f != null); + if (this.amount == (int)FuelAmount.NONE) { + return this.ToExpr(); + } else { + FuelSettingPair setting = null; + var found = translator.fuelContext.TryGetValue(f, out setting); + + if (!found) { // If the context doesn't define fuel for this function, check for a fuel attribute (which supplies a default value if none is found) + setting = FuelAttrib(f); + } + + if (this.amount == (int)FuelAmount.LOW) { + return ToExpr(setting.low); + } else if (this.amount == (int)FuelAmount.HIGH) { + return ToExpr(setting.high); + } else { + Contract.Assert(false); // Should not reach here + return null; + } + } + } + + + /// + /// Finds all fuel related attributes of the form {:fuel function low [high]} + /// Adds the setting to the context _if_ the context does not already have a setting for that function. + /// In other words, it should be called in order from most to least specific contenxt scope. + /// + private static void FindFuelAttributes(Attributes attribs, FuelContext fuelContext) { + Function f = null; + FuelSettingPair setting = null; + + if (attribs != null) { + List> results = Attributes.FindAllExpressions(attribs, "fuel"); + + if (results != null) { + foreach (List args in results) { + if (args != null && args.Count >= 2) { + // Try to extract the function from the first argument + MemberSelectExpr selectExpr = args[0].Resolved as MemberSelectExpr; + if (selectExpr != null) { + f = selectExpr.Member as Function; + } + + // Try to extract the lower fuel setting + LiteralExpr literalLow = args[1] as LiteralExpr; + if (literalLow != null && literalLow.Value is BigInteger) { + setting = new FuelSettingPair(); + setting.low = (int)((BigInteger)literalLow.Value); + } + + // The user may supply an additional high argument; if not, it defaults to low + 1 + if (f != null && args.Count >= 3) { + LiteralExpr literalHigh = args[2] as LiteralExpr; + if (setting != null && literalHigh != null && literalHigh.Value is BigInteger) { + setting.high = (int)((BigInteger)literalHigh.Value); + if (!fuelContext.ContainsKey(f)) { + fuelContext.Add(f, setting); + } + } + } else if (f != null && setting != null) { + setting.high = setting.low + 1; + if (!fuelContext.ContainsKey(f)) { + fuelContext.Add(f, setting); + } + } + } + } + } + } + } + + /// + /// Extend the given context with fuel information from the declaration itself, and enclosing modules + /// + private static void AddFuelContext(FuelContext context, TopLevelDecl decl) { + FindFuelAttributes(decl.Attributes, context); + + var module = decl.Module; + while (module != null) { + FindFuelAttributes(module.Attributes, context); + module = module.Module; + } + } + + /// + /// Creates a summary of all fuel settings in scope, starting from the given class declaration + /// + public static FuelContext NewFuelContext(TopLevelDecl decl) { + FuelContext context = new FuelContext(); + AddFuelContext(context, decl); + return context; + } + + /// + /// Creates a summary of all fuel settings in scope, starting from the given member declaration + /// + public static FuelContext NewFuelContext(MemberDecl decl) { + FuelContext context = new FuelContext(); + + FindFuelAttributes(decl.Attributes, context); + AddFuelContext(context, decl.EnclosingClass); + + return context; + } + + /// + /// Extends the given fuel context with any new fuel settings found in attribs + /// + public static FuelContext ExpandFuelContext(Attributes attribs, FuelContext oldFuelContext) { + Contract.Ensures(SavedContexts.Count == Contract.OldValue(SavedContexts.Count) + 1); + FuelContext newContext = new FuelContext(); + FindFuelAttributes(attribs, newContext); + if (newContext.Count > 0) { + foreach (var pair in oldFuelContext) { + if (!newContext.ContainsKey(pair.Key)) { // Local setting takes precedence over old context + newContext.Add(pair.Key, pair.Value); + } + } + } else { + newContext = oldFuelContext; + } + SavedContexts.Push(oldFuelContext); + return newContext; + } + + public static FuelContext PopFuelContext() { + Contract.Requires(SavedContexts.Count > 0); + return SavedContexts.Pop(); + } + + } + internal class ExpressionTranslator { public readonly Bpl.Expr HeapExpr; @@ -10270,8 +10515,8 @@ namespace Microsoft.Dafny { public readonly string This; public readonly string modifiesFrame; // the name of the context's frame variable. readonly Function applyLimited_CurrentFunction; - public readonly Bpl.Expr layerInterCluster; - public readonly Bpl.Expr layerIntraCluster = null; // a value of null says to do the same as for inter-cluster calls + public readonly FuelSetting layerInterCluster; + public readonly FuelSetting layerIntraCluster = null; // a value of null says to do the same as for inter-cluster calls public int Statistics_CustomLayerFunctionCount = 0; public readonly bool ProducingCoCertificates = false; [ContractInvariantMethod] @@ -10287,41 +10532,17 @@ namespace Microsoft.Dafny { Contract.Invariant(0 <= Statistics_CustomLayerFunctionCount); } - /// - /// This is a general constructor, but takes the layerInterCluster as an int. - /// - ExpressionTranslator(Translator translator, PredefinedDecls predef, Bpl.Expr heap, string thisVar, - Function applyLimited_CurrentFunction, int layerInterCluster, Bpl.Expr layerIntraCluster, string modifiesFrame) { - - Contract.Requires(translator != null); - Contract.Requires(predef != null); - Contract.Requires(heap != null); - Contract.Requires(thisVar != null); - Contract.Requires(0 <= layerInterCluster); - Contract.Requires(modifiesFrame != null); - - this.translator = translator; - this.predef = predef; - this.HeapExpr = heap; - this.This = thisVar; - this.applyLimited_CurrentFunction = applyLimited_CurrentFunction; - this.layerInterCluster = LayerN(layerInterCluster); - this.layerIntraCluster = layerIntraCluster; - this.modifiesFrame = modifiesFrame; - } - /// /// This is the most general constructor. It is private and takes all the parameters. Whenever /// one ExpressionTranslator is constructed from another, unchanged parameters are just copied in. /// ExpressionTranslator(Translator translator, PredefinedDecls predef, Bpl.Expr heap, string thisVar, - Function applyLimited_CurrentFunction, Bpl.Expr layerInterCluster, Bpl.Expr layerIntraCluster, string modifiesFrame) { + Function applyLimited_CurrentFunction, FuelSetting layerInterCluster, FuelSetting layerIntraCluster, string modifiesFrame) { Contract.Requires(translator != null); Contract.Requires(predef != null); Contract.Requires(heap != null); - Contract.Requires(thisVar != null); - Contract.Requires(layerInterCluster != null); + Contract.Requires(thisVar != null); Contract.Requires(modifiesFrame != null); this.translator = translator; @@ -10329,7 +10550,7 @@ namespace Microsoft.Dafny { this.HeapExpr = heap; this.This = thisVar; this.applyLimited_CurrentFunction = applyLimited_CurrentFunction; - this.layerInterCluster = layerInterCluster; + this.layerInterCluster = layerInterCluster; if (layerIntraCluster == null) { this.layerIntraCluster = layerInterCluster; } else { @@ -10365,7 +10586,7 @@ namespace Microsoft.Dafny { } public ExpressionTranslator(Translator translator, PredefinedDecls predef, Bpl.Expr heap, string thisVar) - : this(translator, predef, heap, thisVar, null, 1, null, "$_Frame") { + : this(translator, predef, heap, thisVar, null, new FuelSetting(translator, 1), null, "$_Frame") { Contract.Requires(translator != null); Contract.Requires(predef != null); Contract.Requires(heap != null); @@ -10409,7 +10630,7 @@ namespace Microsoft.Dafny { Contract.Requires(layerArgument != null); Contract.Ensures(Contract.Result() != null); - return new ExpressionTranslator(translator, predef, HeapExpr, This, null, layerArgument, layerArgument, modifiesFrame); + return new ExpressionTranslator(translator, predef, HeapExpr, This, null, new FuelSetting(translator, 0, layerArgument), new FuelSetting(translator, 0, layerArgument), modifiesFrame); } public ExpressionTranslator LimitedFunctions(Function applyLimited_CurrentFunction, Bpl.Expr layerArgument) { @@ -10417,16 +10638,16 @@ namespace Microsoft.Dafny { Contract.Requires(layerArgument != null); Contract.Ensures(Contract.Result() != null); - return new ExpressionTranslator(translator, predef, HeapExpr, This, applyLimited_CurrentFunction, /* layerArgument */ layerInterCluster, layerArgument, modifiesFrame); + return new ExpressionTranslator(translator, predef, HeapExpr, This, applyLimited_CurrentFunction, /* layerArgument */ layerInterCluster, new FuelSetting(translator, 0, layerArgument), modifiesFrame); } public ExpressionTranslator LayerOffset(int offset) { Contract.Requires(0 <= offset); Contract.Ensures(Contract.Result() != null); - var et = new ExpressionTranslator(translator, predef, HeapExpr, This, applyLimited_CurrentFunction, translator.LayerSucc(layerInterCluster, offset), layerIntraCluster, modifiesFrame); + var et = new ExpressionTranslator(translator, predef, HeapExpr, This, applyLimited_CurrentFunction, layerInterCluster.Offset(offset), layerIntraCluster, modifiesFrame); if (this.oldEtran != null) { - var etOld = new ExpressionTranslator(translator, predef, Old.HeapExpr, This, applyLimited_CurrentFunction, translator.LayerSucc(layerInterCluster, offset), layerIntraCluster, modifiesFrame); + var etOld = new ExpressionTranslator(translator, predef, Old.HeapExpr, This, applyLimited_CurrentFunction, layerInterCluster.Offset(offset), layerIntraCluster, modifiesFrame); etOld.oldEtran = etOld; et.oldEtran = etOld; } @@ -10465,17 +10686,6 @@ namespace Microsoft.Dafny { } } - public Bpl.Expr LayerZero() { - Contract.Ensures(Contract.Result() != null); - return new Bpl.IdentifierExpr(Token.NoToken, "$LZ", predef.LayerType); - } - - public Bpl.Expr LayerN(int n) { - Contract.Requires(0 <= n); - Contract.Ensures(Contract.Result() != null); - return translator.LayerSucc(LayerZero(), n); - } - public Bpl.IdentifierExpr ModuleContextHeight() { Contract.Ensures(Contract.Result().Type != null); return new Bpl.IdentifierExpr(Token.NoToken, "$ModuleContextHeight", Bpl.Type.Int); @@ -10649,8 +10859,8 @@ namespace Microsoft.Dafny { }, fn => { var args = e.TypeApplication.ConvertAll(translator.TypeToTy); - if (fn.IsRecursive) { - args.Add(layerInterCluster); + if (fn.IsFuelAware()) { + args.Add(this.layerInterCluster.GetFunctionFuel(fn)); } if (!fn.IsStatic) { args.Add(/* translator.BoxIfUnboxed */(TrExpr(e.Obj)/*, e.Type */)); @@ -10806,15 +11016,15 @@ namespace Microsoft.Dafny { } else if (expr is FunctionCallExpr) { FunctionCallExpr e = (FunctionCallExpr)expr; Bpl.Expr layerArgument; - if (e.Function.IsRecursive) { + if (e.Function.IsFuelAware()) { Statistics_CustomLayerFunctionCount++; ModuleDefinition module = e.Function.EnclosingClass.Module; if (this.applyLimited_CurrentFunction != null && this.layerIntraCluster != null && ModuleDefinition.InSameSCC(e.Function, applyLimited_CurrentFunction)) { - layerArgument = this.layerIntraCluster; + layerArgument = this.layerIntraCluster.GetFunctionFuel(e.Function); } else { - layerArgument = this.layerInterCluster; + layerArgument = this.layerInterCluster.GetFunctionFuel(e.Function); } } else { layerArgument = null; @@ -10992,7 +11202,7 @@ namespace Microsoft.Dafny { if (cot != null) { var e0args = e.E0.Type.NormalizeExpand().TypeArgs; var e1args = e.E1.Type.NormalizeExpand().TypeArgs; - return translator.CoEqualCall(cot, e0args, e1args, null, LayerN(2), e0, e1, expr.tok); + return translator.CoEqualCall(cot, e0args, e1args, null, this.layerInterCluster.LayerN((int)FuelSetting.FuelAmount.HIGH), e0, e1, expr.tok); } typ = Bpl.Type.Bool; bOpcode = BinaryOperator.Opcode.Eq; break; @@ -11001,7 +11211,7 @@ namespace Microsoft.Dafny { if (cotx != null) { var e0args = e.E0.Type.NormalizeExpand().TypeArgs; var e1args = e.E1.Type.NormalizeExpand().TypeArgs; - var x = translator.CoEqualCall(cotx, e0args, e1args, null, LayerN(2), e0, e1, expr.tok); + var x = translator.CoEqualCall(cotx, e0args, e1args, null, this.layerInterCluster.LayerN((int)FuelSetting.FuelAmount.HIGH), e0, e1, expr.tok); return Bpl.Expr.Unary(expr.tok, UnaryOperator.Opcode.Not, x); } typ = Bpl.Type.Bool; @@ -11282,7 +11492,7 @@ namespace Microsoft.Dafny { var e2type = e.E2.Type.NormalizeExpand(); var cot = e1type.AsCoDatatype; Contract.Assert(cot != null); // the argument types of prefix equality (and prefix disequality) are codatatypes - var r = translator.CoEqualCall(cot, e1type.TypeArgs, e2type.TypeArgs, e0, LayerN(2), e1, e2); + var r = translator.CoEqualCall(cot, e1type.TypeArgs, e2type.TypeArgs, e0, this.layerInterCluster.LayerN((int)FuelSetting.FuelAmount.HIGH), e1, e2); if (e.Op == TernaryExpr.Opcode.PrefixEqOp) { return r; } else { @@ -11315,8 +11525,7 @@ namespace Microsoft.Dafny { if (Attributes.ContainsBool(e.Attributes, "layerQuantifier", ref _scratch)) { // If this is a layer quantifier, quantify over layers here, and use $LS(ly) layers in the translation of the body var ly = BplBoundVar(e.Refresh("q$ly#", translator.CurrentIdGenerator), predef.LayerType, bvars); - Expr layer = translator.LayerSucc(ly); - bodyEtran = new ExpressionTranslator(translator, predef, HeapExpr, This, applyLimited_CurrentFunction, layer, layer, modifiesFrame); + bodyEtran = new ExpressionTranslator(translator, predef, HeapExpr, This, applyLimited_CurrentFunction, new FuelSetting(translator, 1, ly), new FuelSetting(translator, 1, ly), modifiesFrame); } if (Attributes.ContainsBool(e.Attributes, "heapQuantifier", ref _scratch)) { var h = BplBoundVar(e.Refresh("q$heap#", translator.CurrentIdGenerator), predef.HeapType, bvars); @@ -11489,7 +11698,7 @@ namespace Microsoft.Dafny { new Bpl.LambdaExpr(e.tok, new List(), bvars, null, ebody), new Bpl.LambdaExpr(e.tok, new List(), bvars, null, reqbody), new Bpl.LambdaExpr(e.tok, new List(), bvars, null, rdbody))), - layerIntraCluster ?? layerInterCluster), + layerIntraCluster != null ? layerIntraCluster.ToExpr() : layerInterCluster.ToExpr()), predef.HandleType); } @@ -12582,15 +12791,14 @@ namespace Microsoft.Dafny { // checked $PrefixEqual#Dt(k, A, B) || (0 < k ==> A.Cons? ==> B.Cons? && A.head == B.head && $PrefixEqual#2#Dt(k - 1, A.tail, B.tail)) // note the #2 in the recursive call, just like for user-defined predicates that are inlined by TrSplitExpr // free $PrefixEqual#Dt(k, A, B); var kPos = Bpl.Expr.Lt(Bpl.Expr.Literal(0), k); - var prefixEqK = CoEqualCall(codecl, e1type.TypeArgs, e2type.TypeArgs, k, etran.LayerN(2), A, B); // FunctionCall(expr.tok, CoPrefixName(codecl, 1), Bpl.Type.Bool, k, A, B); + var prefixEqK = CoEqualCall(codecl, e1type.TypeArgs, e2type.TypeArgs, k, etran.layerInterCluster.LayerN((int)FuelSetting.FuelAmount.HIGH), A, B); // FunctionCall(expr.tok, CoPrefixName(codecl, 1), Bpl.Type.Bool, k, A, B); var kMinusOne = Bpl.Expr.Sub(k, Bpl.Expr.Literal(1)); // for the inlining of the definition of prefix equality, translate the two main equality operands arguments with a higher offset (to obtain #2 functions) var etran2 = etran.LayerOffset(1); var A2 = etran2.TrExpr(e.E1); var B2 = etran2.TrExpr(e.E2); var needsTokenAdjust = TrSplitNeedsTokenAdjustment(expr); - // Dan: dafny4/Circ.dfy needs this one to be 2+, rather than 1+ - Bpl.Expr layer = LayerSucc(etran.layerInterCluster, 2); + Bpl.Expr layer = etran.layerInterCluster.LayerN((int)FuelSetting.FuelAmount.HIGH); foreach (var c in CoPrefixEquality(needsTokenAdjust ? new ForceCheckToken(expr.tok) : expr.tok, codecl, e1type.TypeArgs, e2type.TypeArgs, kMinusOne, layer, A2, B2, true)) { var p = Bpl.Expr.Binary(c.tok, BinaryOperator.Opcode.Or, prefixEqK, Bpl.Expr.Imp(kPos, c)); splits.Add(new SplitExprInfo(SplitExprInfo.K.Checked, p)); @@ -13944,7 +14152,7 @@ namespace Microsoft.Dafny { r = rr; } else if (stmt is CalcStmt) { var s = (CalcStmt)stmt; - var rr = new CalcStmt(s.Tok, s.EndTok, SubstCalcOp(s.Op), s.Lines.ConvertAll(Substitute), s.Hints.ConvertAll(SubstBlockStmt), s.StepOps.ConvertAll(SubstCalcOp), SubstCalcOp(s.ResultOp)); + var rr = new CalcStmt(s.Tok, s.EndTok, SubstCalcOp(s.Op), s.Lines.ConvertAll(Substitute), s.Hints.ConvertAll(SubstBlockStmt), s.StepOps.ConvertAll(SubstCalcOp), SubstCalcOp(s.ResultOp), SubstAttributes(s.Attributes)); rr.Steps.AddRange(s.Steps.ConvertAll(Substitute)); rr.Result = Substitute(s.Result); r = rr; diff --git a/Test/dafny0/Fuel.dfy b/Test/dafny0/Fuel.dfy new file mode 100644 index 00000000..c8a1fc2f --- /dev/null +++ b/Test/dafny0/Fuel.dfy @@ -0,0 +1,423 @@ +// RUN: %dafny /compile:0 /print:"%t.print" /dprint:"%t.dprint" "%s" > "%t" +// RUN: %diff "%s.expect" "%t" + +module TestModule1 { + function pos(x:int) : int + { + if x < 0 then 0 + else 1 + pos(x - 1) + } + + method test(y:int, z:int) + requires y > 5; + requires z < 0; + { + assert pos(z) == 0; + assert pos(-1) == 0; + assert pos(y) == 3 + pos(y - 3); // error: Should fail, due to lack of fuel + assert pos(y) == 4 + pos(y - 4); // Succeeds, thanks to the assume from the preceding assert + } +} + +// Test with function-level fuel boost +module TestModule2 { + function {:fuel 3} pos1(x:int) : int + { + if x < 0 then 0 + else 1 + pos1(x - 1) + } + + function {:fuel 3,5} pos2(x:int) : int + { + if x < 0 then 0 + else 1 + pos2(x - 1) + } + + function {:fuel 3,5} pos3(x:int) : int + { + if x < 0 then 0 + else 1 + pos3(x - 1) + } + + function {:opaque} {:fuel 3,5} pos4(x:int) : int + { + if x < 0 then 0 + else 1 + pos3(x - 1) + } + + method test(y:int, z:int) + requires y > 5; + requires z < 0; + { + assert pos1(z) == 0; + assert pos1(-1) == 0; + assert pos1(y) == 3 + pos1(y - 3); + assert pos1(y) == 4 + pos1(y - 4); + + assert pos2(z) == 0; + assert pos2(-1) == 0; + assert pos2(y) == 3 + pos2(y - 3); + assert pos2(y) == 4 + pos2(y - 4); + + if (*) { + assert pos3(y) == 5 + pos3(y - 5); // Just enough fuel to get here + } else { + assert pos3(y) == 6 + pos3(y - 6); // error: Should fail even with a boost, since boost is too small + } + + if (*) { + assert pos4(z) == 0; // error: Fuel shouldn't overcome opaque + } else { + reveal_pos4(); + assert pos4(y) == 5 + pos4(y - 5); // With reveal, everything should work as above + } + + + } +} + + +module TestModule3 { + // This fuel setting is equivalent to opaque, except for literals + function {:fuel 0,0} pos(x:int) : int + { + if x < 0 then 0 + else 1 + pos(x - 1) + } + + method test(y:int, z:int) + requires y > 5; + requires z < 0; + { + assert pos(z) == 0; // error: Opaque setting hides body + assert pos(-1) == 0; // Passes, since Dafny's computation mode for lits ignore fuel + assert pos(y) == 3 + pos(y - 3);// error: Opaque setting hides body + } +} + +// Test fuel settings via different contexts +module TestModule4 { + function pos(x:int) : int + { + if x < 0 then 0 + else 1 + pos(x - 1) + } + + // Should pass + method {:fuel pos,3,5} test1(y:int, z:int) + requires y > 5; + requires z < 0; + { + assert pos(z) == 0; + assert pos(-1) == 0; + assert pos(y) == 3 + pos(y - 3); + } + + method {:fuel pos,0,0} test2(y:int, z:int) + requires y > 5; + requires z < 0; + { + assert pos(z) == 0; // error: Should fail due to "opaque" fuel setting + assert pos(-1) == 0; + assert pos(y) == 3 + pos(y - 3); // error: Should fail due to "opaque" fuel setting + } + + method test3(y:int, z:int) + requires y > 5; + requires z < 0; + { + assert {:fuel pos,0,0} pos(z) == 0; // error: Should fail due to "opaque" fuel setting + assert pos(-1) == 0; + if (*) { + assert pos(y) == 3 + pos(y - 3); // error: Should fail without extra fuel setting + assert pos(y) == 6 + pos(y - 6); // error: Should fail even with previous assert turned into assume + } else { + assert {:fuel pos,3,5} pos(y) == 3 + pos(y - 3); // Should succeed with extra fuel setting + assert pos(y) == 6 + pos(y - 6); // Should succeed thanks to previous assert turned into assume + } + } + + method test4(y:int, z:int) + requires y > 5; + requires z < 0; + { + forall t:int {:fuel pos,3} | t > 0 + ensures true; + { + assert pos(y) == 3 + pos(y - 3); // Expected to pass, due to local fuel boost + } + + if (*) { + calc {:fuel pos,3} { + pos(y); + 3 + pos(y - 3); + } + } + + assert pos(y) == 3 + pos(y - 3); // error: Should fail, due to lack of fuel outside the forall + } +} + +// Test fuel settings via different module contexts +module TestModule5 { + // Test module level fuel settings, with nested modules + + module TestModule5a { + module {:fuel TestModule5aiA.pos,3} TestModule5ai { + module TestModule5aiA { + function pos(x:int) : int + { + if x < 0 then 0 + else 1 + pos(x - 1) + } + + method test(y:int, z:int) + requires y > 5; + requires z < 0; + { + assert pos(z) == 0; + assert pos(-1) == 0; + assert pos(y) == 3 + pos(y - 3); // Should pass due to intermediate module's fuel setting + } + } + + method test(y:int, z:int) + requires y > 5; + requires z < 0; + { + assert TestModule5aiA.pos(z) == 0; + assert TestModule5aiA.pos(-1) == 0; + assert TestModule5aiA.pos(y) == 3 + TestModule5aiA.pos(y - 3); // Should pass due to module level fuel + } + } + + method test(y:int, z:int) + requires y > 5; + requires z < 0; + { + assert TestModule5ai.TestModule5aiA.pos(z) == 0; + assert TestModule5ai.TestModule5aiA.pos(-1) == 0; + assert TestModule5ai.TestModule5aiA.pos(y) == 3 + TestModule5ai.TestModule5aiA.pos(y - 3); // error: Should fail, due to lack of fuel + } + } + + module {:fuel TestModule5bi.TestModule5biA.pos,3} TestModule5b { + module TestModule5bi { + module TestModule5biA { + function pos(x:int) : int + { + if x < 0 then 0 + else 1 + pos(x - 1) + } + + method test(y:int, z:int) + requires y > 5; + requires z < 0; + { + assert pos(z) == 0; + assert pos(-1) == 0; + assert pos(y) == 3 + pos(y - 3); // Should succceed due to outer module fuel setting + } + } + } + } +} + +// Test fuel setting for multiple functions +module TestModule6 { + function pos(x:int) : int + { + if x < 0 then 0 + else 1 + pos(x - 1) + } + + function neg(x:int) : int + decreases 1 - x; + { + if x > 0 then 0 + else 1 + neg(x + 1) + } + + method test1(y:int, z:int) + requires y > 5; + requires z < 5; + { + assert pos(y) == 3 + pos(y - 3); // error: Should fail, due to lack of fuel + + assert neg(z) == 3 + neg(z + 3); // error: Should fail, due to lack of fuel + } + + method {:fuel pos,3} {:fuel neg,4} test2(y:int, z:int) + requires y > 5; + requires z < -5; + { + assert pos(y) == 3 + pos(y - 3); + + assert neg(z) == 3 + neg(z + 3); + } +} + +// Test fuel settings with multiple overlapping contexts +module TestModule7 { + function {:fuel 3} pos(x:int) : int + { + if x < 0 then 0 + else 1 + pos(x - 1) + } + + function {:fuel 0,0} neg(x:int) : int + decreases 1 - x; + { + if x > 0 then 0 + else 1 + neg(x + 1) + } + + method {:fuel neg,4} {:fuel pos,0,0} test1(y:int, z:int) + requires y > 5; + requires z < -5; + { + if (*) { + assert pos(y) == 3 + pos(y - 3); // error: Method fuel should override function fuel, so this should fail + assert neg(z) == 3 + neg(z + 3); // Method fuel should override function fuel, so this succeeds + } + + forall t:int {:fuel pos,3} | t > 0 + ensures true; + { + assert pos(y) == 3 + pos(y - 3); // Statement fuel should override method fuel, so this should succeed + } + } +} + +// Test fuel in a slightly more complicated setting +module TestModule8 { + + newtype byte = i:int | 0 <= i < 0x100 + newtype uint64 = i:int | 0 <= i < 0x10000000000000000 + + datatype G = GUint64 + | GArray(elt:G) + | GTuple(t:seq) + | GByteArray + | GTaggedUnion(cases:seq) + + datatype V = VUint64(u:uint64) + | VTuple(t:seq) + | VCase(c:uint64, val:V) + + predicate {:fuel 2} ValInGrammar(val:V, grammar:G) + { + match val + case VUint64(_) => grammar.GUint64? + case VTuple(t) => grammar.GTuple? && |t| == |grammar.t| + && forall i :: 0 <= i < |t| ==> ValInGrammar(t[i], grammar.t[i]) + case VCase(c, val) => grammar.GTaggedUnion? && int(c) < |grammar.cases| && ValInGrammar(val, grammar.cases[c]) + } + + datatype CRequest = CRequest(client:EndPoint, seqno:uint64, request:CAppMessage) | CRequestNoOp() + + type EndPoint + function method EndPoint_grammar() : G { GUint64 } + function method CRequest_grammar() : G { GTaggedUnion([ GTuple([EndPoint_grammar(), GUint64, CAppMessage_grammar()]), GUint64]) } + + function method parse_EndPoint(val:V) : EndPoint + requires ValInGrammar(val, EndPoint_grammar()); + + type CAppMessage + function method CAppMessage_grammar() : G { GTaggedUnion([GUint64, GUint64, GUint64]) } + function method parse_AppMessage(val:V) : CAppMessage + requires ValInGrammar(val, CAppMessage_grammar()); + + function method {:fuel ValInGrammar,1,2} parse_Request1(val:V) : CRequest + requires ValInGrammar(val, CRequest_grammar()); + { + if val.c == 0 then + var ep := parse_EndPoint(val.val.t[0]); // With default fuel, error: function precondition, destructor, index + CRequest(ep, val.val.t[1].u, parse_AppMessage(val.val.t[2])) // error: index out of range, destructor + else + CRequestNoOp() + } + + function method parse_Request2(val:V) : CRequest + requires ValInGrammar(val, CRequest_grammar()); + { + if val.c == 0 then + var ep := parse_EndPoint(val.val.t[0]); // With fuel boosted to 2 this succeeds + CRequest(ep, val.val.t[1].u, parse_AppMessage(val.val.t[2])) // error: destructor + else + CRequestNoOp() + } + + function method {:fuel ValInGrammar,3} parse_Request3(val:V) : CRequest + requires ValInGrammar(val, CRequest_grammar()); + { + if val.c == 0 then + var ep := parse_EndPoint(val.val.t[0]); + CRequest(ep, val.val.t[1].u, parse_AppMessage(val.val.t[2])) // With one more boost, everything succeeds + else + CRequestNoOp() + } + + // With the method, everything succeeds with one less fuel boost (i.e., 2, rather than 3, as in parse_Request3) + method parse_Request4(val:V) returns (req:CRequest) + requires ValInGrammar(val, CRequest_grammar()); + { + if val.c == 0 { + var ep := parse_EndPoint(val.val.t[0]); + req := CRequest(ep, val.val.t[1].u, parse_AppMessage(val.val.t[2])); + } else { + req := CRequestNoOp(); + } + } +} + + +// Test fuel when it's applied to a non-recursive function +module TestModule9 { + function abs(x:int) : int + { + if x < 0 then -1 * x else x + } + + // All should pass. + method test1(y:int, z:int) + requires y > 5; + requires z < 0; + { + assert abs(z) == -1*z; + assert abs(y) == y; + assert abs(-1) == 1; + } + + // Method-level fuel override + method {:fuel abs,0,0} test2(y:int, z:int) + requires y > 5; + requires z < 0; + { + assert abs(z) == -1*z; // error: Cannot see the body of abs + assert abs(y) == y; // error: Cannot see the body of abs + assert abs(-1) == 1; // lit bypasses fuel, so this should succeed + } + + // Statement-level fuel override + method test3(y:int, z:int) + requires y > 5; + requires z < 0; + { + assert {:fuel abs,0,0} abs(z) == -1*z; // error: Cannot see the body of abs + assert abs(y) == y; // Normal success + assert abs(-1) == 1; // lit bypasses fuel, so this should succeed + } + + // Giving more fuel to a non-recursive function won't help, + // but it shouldn't hurt either. + method {:fuel abs,5,7} test4(y:int, z:int) + requires y > 5; + requires z < 0; + { + assert abs(z) == -1*z; + assert abs(y) == y; + assert abs(-1) == 1; + } +} + diff --git a/Test/dafny0/Fuel.dfy.expect b/Test/dafny0/Fuel.dfy.expect new file mode 100644 index 00000000..4c180a9c --- /dev/null +++ b/Test/dafny0/Fuel.dfy.expect @@ -0,0 +1,95 @@ +Fuel.dfy(17,23): Error: assertion violation +Execution trace: + (0,0): anon0 +Fuel.dfy(65,28): Error: assertion violation +Execution trace: + (0,0): anon0 + (0,0): anon6_Else +Fuel.dfy(69,28): Error: assertion violation +Execution trace: + (0,0): anon0 + (0,0): anon6_Then + (0,0): anon7_Then +Fuel.dfy(92,23): Error: assertion violation +Execution trace: + (0,0): anon0 +Fuel.dfy(94,23): Error: assertion violation +Execution trace: + (0,0): anon0 +Fuel.dfy(120,23): Error: assertion violation +Execution trace: + (0,0): anon0 +Fuel.dfy(122,23): Error: assertion violation +Execution trace: + (0,0): anon0 +Fuel.dfy(129,39): Error: assertion violation +Execution trace: + (0,0): anon0 +Fuel.dfy(132,27): Error: assertion violation +Execution trace: + (0,0): anon0 + (0,0): anon3_Then +Fuel.dfy(133,27): Error: assertion violation +Execution trace: + (0,0): anon0 + (0,0): anon3_Then +Fuel.dfy(157,23): Error: assertion violation +Execution trace: + (0,0): anon0 + (0,0): anon10_Else + (0,0): anon9 +Fuel.dfy(200,56): Error: assertion violation +Execution trace: + (0,0): anon0 +Fuel.dfy(245,23): Error: assertion violation +Execution trace: + (0,0): anon0 +Fuel.dfy(247,23): Error: assertion violation +Execution trace: + (0,0): anon0 +Fuel.dfy(280,27): Error: assertion violation +Execution trace: + (0,0): anon0 + (0,0): anon7_Then +Fuel.dfy(335,27): Error: possible violation of function precondition +Fuel.dfy(324,22): Related location +Execution trace: + (0,0): anon0 + (0,0): anon7_Else + (0,0): anon8_Then +Fuel.dfy(335,50): Error: destructor 't' can only be applied to datatype values constructed by 'VTuple' +Execution trace: + (0,0): anon0 + (0,0): anon7_Else + (0,0): anon8_Then +Fuel.dfy(335,51): Error: index out of range +Execution trace: + (0,0): anon0 + (0,0): anon7_Else + (0,0): anon8_Then +Fuel.dfy(336,39): Error: index out of range +Execution trace: + (0,0): anon0 + (0,0): anon7_Else + (0,0): anon8_Then +Fuel.dfy(336,43): Error: destructor 'u' can only be applied to datatype values constructed by 'VUint64' +Execution trace: + (0,0): anon0 + (0,0): anon7_Else + (0,0): anon8_Then +Fuel.dfy(346,43): Error: destructor 'u' can only be applied to datatype values constructed by 'VUint64' +Execution trace: + (0,0): anon0 + (0,0): anon7_Else + (0,0): anon8_Then +Fuel.dfy(397,23): Error: assertion violation +Execution trace: + (0,0): anon0 +Fuel.dfy(398,23): Error: assertion violation +Execution trace: + (0,0): anon0 +Fuel.dfy(407,39): Error: assertion violation +Execution trace: + (0,0): anon0 + +Dafny program verifier finished with 51 verified, 24 errors diff --git a/Test/dafny4/Circ.dfy b/Test/dafny4/Circ.dfy index e7609195..d110c05c 100644 --- a/Test/dafny4/Circ.dfy +++ b/Test/dafny4/Circ.dfy @@ -16,6 +16,7 @@ function zip(a: Stream, b: Stream): Stream { Cons(a.head, zip(b, a.tail)) } colemma BlinkZipProperty() ensures zip(zeros(), ones()) == blink(); { + BlinkZipProperty(); } // ----- Thue-Morse sequence ----- @@ -75,6 +76,7 @@ colemma FProperty(s: Stream) // def. zip Cons(s.head, Cons(not(s).head, zip(s.tail, not(s).tail))); } + FProperty(s.tail); } // The fix-point theorem now follows easily. -- cgit v1.2.3 From 85d4456ccf1e1d8c456dffa012d3f3d724f50a4a Mon Sep 17 00:00:00 2001 From: Michael Lowell Roberts Date: Thu, 2 Jul 2015 15:00:52 -0700 Subject: multiple changes... - fix for requirement inheritance in refinement. - minimimally viable implementation of exclusive refinement feature. --- Source/Dafny/Cloner.cs | 11 +- Source/Dafny/Dafny.atg | 5 +- Source/Dafny/DafnyAst.cs | 119 ++++- Source/Dafny/Makefile | 4 +- Source/Dafny/Parser.cs | 962 +++++++++++++++++----------------- Source/Dafny/RefinementTransformer.cs | 9 + Source/Dafny/Resolver.cs | 71 ++- Source/Dafny/Scanner.cs | 198 +++---- Source/Dafny/Translator.cs | 4 +- 9 files changed, 768 insertions(+), 615 deletions(-) (limited to 'Source/Dafny/Scanner.cs') diff --git a/Source/Dafny/Cloner.cs b/Source/Dafny/Cloner.cs index e313ffac..6e64c7ec 100644 --- a/Source/Dafny/Cloner.cs +++ b/Source/Dafny/Cloner.cs @@ -17,12 +17,15 @@ namespace Microsoft.Dafny if (m is DefaultModuleDecl) { nw = new DefaultModuleDecl(); } else { - nw = new ModuleDefinition(Tok(m.tok), name, m.IsAbstract, m.IsFacade, m.RefinementBaseName, m.Module, CloneAttributes(m.Attributes), true); + nw = new ModuleDefinition(Tok(m.tok), name, m.IsAbstract, m.IsFacade, m.IsExclusiveRefinement, m.RefinementBaseName, m.Module, CloneAttributes(m.Attributes), true); } foreach (var d in m.TopLevelDecls) { nw.TopLevelDecls.Add(CloneDeclaration(d, nw)); } - nw.RefinementBase = m.RefinementBase; + if (null != m.RefinementBase) { + nw.RefinementBase = m.RefinementBase; + } + nw.ClonedFrom = m; nw.Height = m.Height; return nw; } @@ -33,7 +36,7 @@ namespace Microsoft.Dafny if (d is OpaqueTypeDecl) { var dd = (OpaqueTypeDecl)d; - return new OpaqueTypeDecl(Tok(dd.tok), dd.Name, m, dd.EqualitySupport, dd.TypeArgs.ConvertAll(CloneTypeParam), CloneAttributes(dd.Attributes)); + return new OpaqueTypeDecl(Tok(dd.tok), dd.Name, m, dd.EqualitySupport, dd.TypeArgs.ConvertAll(CloneTypeParam), CloneAttributes(dd.Attributes), d); } else if (d is TypeSynonymDecl) { var dd = (TypeSynonymDecl)d; var tps = dd.TypeArgs.ConvertAll(CloneTypeParam); @@ -138,7 +141,7 @@ namespace Microsoft.Dafny } public TypeParameter CloneTypeParam(TypeParameter tp) { - return new TypeParameter(Tok(tp.tok), tp.Name, tp.EqualitySupport); + return new TypeParameter(Tok(tp.tok), tp.Name, tp.EqualitySupport, tp); } public MemberDecl CloneMember(MemberDecl member) { diff --git a/Source/Dafny/Dafny.atg b/Source/Dafny/Dafny.atg index 5d4a4321..7b51fb5e 100644 --- a/Source/Dafny/Dafny.atg +++ b/Source/Dafny/Dafny.atg @@ -542,6 +542,7 @@ SubModuleDecl ModuleDecl sm; submodule = null; // appease compiler bool isAbstract = false; + bool isExclusively = false; bool opened = false; .) ( [ "abstract" (. isAbstract = true; .) ] @@ -549,7 +550,9 @@ SubModuleDecl { Attribute } NoUSIdent - [ "refines" QualifiedModuleName ] (. module = new ModuleDefinition(id, id.val, isAbstract, false, idRefined == null ? null : idRefined, parent, attrs, false); .) + [ "exclusively" "refines" QualifiedModuleName (. isExclusively = true; .) + | "refines" QualifiedModuleName (. isExclusively = false; .) ] + (. module = new ModuleDefinition(id, id.val, isAbstract, false, isExclusively, idRefined == null ? null : idRefined, parent, attrs, false, this); .) "{" (. module.BodyStartTok = t; .) { SubModuleDecl (. module.TopLevelDecls.Add(sm); .) | ClassDecl (. module.TopLevelDecls.Add(c); .) diff --git a/Source/Dafny/DafnyAst.cs b/Source/Dafny/DafnyAst.cs index 712cb00a..134fb4c1 100644 --- a/Source/Dafny/DafnyAst.cs +++ b/Source/Dafny/DafnyAst.cs @@ -86,7 +86,7 @@ namespace Microsoft.Dafny { public class BuiltIns { - public readonly ModuleDefinition SystemModule = new ModuleDefinition(Token.NoToken, "_System", false, false, null, null, null, true); + public readonly ModuleDefinition SystemModule = new ModuleDefinition(Token.NoToken, "_System", false, false, /*isExclusiveRefinement:*/ false, null, null, null, true); readonly Dictionary arrayTypeDecls = new Dictionary(); readonly Dictionary arrowTypeDecls = new Dictionary(); readonly Dictionary tupleTypeDecls = new Dictionary(); @@ -1486,6 +1486,8 @@ namespace Microsoft.Dafny { IToken INamedRegion.BodyEndTok { get { return BodyEndTok; } } string INamedRegion.Name { get { return Name; } } string compileName; + private readonly Declaration clonedFrom; + public virtual string CompileName { get { if (compileName == null) { @@ -1496,12 +1498,19 @@ namespace Microsoft.Dafny { } public Attributes Attributes; // readonly, except during class merging in the refinement transformations - public Declaration(IToken tok, string name, Attributes attributes) { + public Declaration(IToken tok, string name, Attributes attributes, Declaration clonedFrom) { Contract.Requires(tok != null); Contract.Requires(name != null); this.tok = tok; this.Name = name; this.Attributes = attributes; + this.clonedFrom = clonedFrom; + } + + public Declaration ClonedFrom { + get { + return this.clonedFrom; + } } [Pure] @@ -1513,12 +1522,10 @@ namespace Microsoft.Dafny { internal FreshIdGenerator IdGenerator = new FreshIdGenerator(); } - public class OpaqueType_AsParameter : TypeParameter - { + public class OpaqueType_AsParameter : TypeParameter { public readonly List TypeArgs; public OpaqueType_AsParameter(IToken tok, string name, EqualitySupportValue equalitySupport, List typeArgs) - : base(tok, name, equalitySupport) - { + : base(tok, name, equalitySupport) { Contract.Requires(tok != null); Contract.Requires(name != null); Contract.Requires(typeArgs != null); @@ -1566,8 +1573,8 @@ namespace Microsoft.Dafny { } public int PositionalIndex; // which type parameter this is (ie. in C, S is 0, T is 1 and U is 2). - public TypeParameter(IToken tok, string name, EqualitySupportValue equalitySupport = EqualitySupportValue.Unspecified) - : base(tok, name, null) { + public TypeParameter(IToken tok, string name, EqualitySupportValue equalitySupport = EqualitySupportValue.Unspecified, Declaration clonedFrom = null) + : base(tok, name, null, clonedFrom) { Contract.Requires(tok != null); Contract.Requires(name != null); EqualitySupport = equalitySupport; @@ -1642,7 +1649,7 @@ namespace Microsoft.Dafny { } public class ModuleSignature { - + private ModuleDefinition exclusiveRefinement = null; public readonly Dictionary TopLevels = new Dictionary(); public readonly Dictionary> Ctors = new Dictionary>(); public readonly Dictionary StaticMembers = new Dictionary(); @@ -1663,6 +1670,25 @@ namespace Microsoft.Dafny { return false; } } + + public ModuleDefinition ExclusiveRefinement { + get { + if (null == exclusiveRefinement) { + return ModuleDef == null ? null : ModuleDef.ExclusiveRefinement; + } else { + return exclusiveRefinement; + } + } + + set { + if (null == ExclusiveRefinement) { + exclusiveRefinement = null; + } else { + throw new InvalidOperationException("An exclusive refinement relationship cannot be amended."); + } + } + } + } public class ModuleDefinition : INamedRegion @@ -1678,22 +1704,64 @@ namespace Microsoft.Dafny { public readonly Attributes Attributes; public readonly List RefinementBaseName; // null if no refinement base public ModuleDecl RefinementBaseRoot; // filled in early during resolution, corresponds to RefinementBaseName[0] - public ModuleDefinition RefinementBase; // filled in during resolution (null if no refinement base) + public List Includes; public readonly List TopLevelDecls = new List(); // filled in by the parser; readonly after that public readonly Graph CallGraph = new Graph(); // filled in during resolution public int Height; // height in the topological sorting of modules; filled in during resolution public readonly bool IsAbstract; + public readonly bool IsExclusiveRefinement; public readonly bool IsFacade; // True iff this module represents a module facade (that is, an abstract interface) private readonly bool IsBuiltinName; // true if this is something like _System that shouldn't have it's name mangled. + + private ModuleDefinition exclusiveRefinement; + + public ModuleDefinition ExclusiveRefinement { + get { return exclusiveRefinement; } + set { + if (null == exclusiveRefinement) { + if (!value.IsExclusiveRefinement) { + throw new ArgumentException( + string.Format("Exclusive refinement of {0} with 'new' module {0} is disallowed.", + Name, + value.Name)); + } + // todo: validate state of `value`. + exclusiveRefinement = value; + } else { + throw new InvalidOperationException(string.Format("Exclusive refinement of {0} has already been established {1}; cannot reestabilish as {2}.", Name, exclusiveRefinement.Name, value.Name)); + } + } + } + + public int ExclusiveRefinementCount { get; set; } + + private ModuleDefinition refinementBase; // filled in during resolution via RefinementBase property (null if no refinement base yet or at all). + + public ModuleDefinition RefinementBase { + get { + return refinementBase; + } + + set { + // the refinementBase member may only be changed once. + if (null != refinementBase) { + throw new InvalidOperationException(string.Format("This module ({0}) already has a refinement base ({1}).", Name, refinementBase.Name)); + } + refinementBase = value; + } + } + + public ModuleDefinition ClonedFrom { get; set; } + [ContractInvariantMethod] void ObjectInvariant() { Contract.Invariant(cce.NonNullElements(TopLevelDecls)); Contract.Invariant(CallGraph != null); } - public ModuleDefinition(IToken tok, string name, bool isAbstract, bool isFacade, List refinementBase, ModuleDefinition parent, Attributes attributes, bool isBuiltinName) + public ModuleDefinition(IToken tok, string name, bool isAbstract, bool isFacade, bool isExclusiveRefinement, List refinementBase, ModuleDefinition parent, Attributes attributes, bool isBuiltinName, Parser parser = null) { Contract.Requires(tok != null); Contract.Requires(name != null); @@ -1704,8 +1772,9 @@ namespace Microsoft.Dafny { RefinementBaseName = refinementBase; IsAbstract = isAbstract; IsFacade = isFacade; + IsExclusiveRefinement = isExclusiveRefinement; RefinementBaseRoot = null; - RefinementBase = null; + this.refinementBase = null; Includes = new List(); IsBuiltinName = isBuiltinName; } @@ -1844,7 +1913,9 @@ namespace Microsoft.Dafny { } public class DefaultModuleDecl : ModuleDefinition { - public DefaultModuleDecl() : base(Token.NoToken, "_module", false, false, null, null, null, true) { + public DefaultModuleDecl() + : base(Token.NoToken, "_module", false, false, /*isExclusiveRefinement:*/ false, null, null, null, true) + { } public override bool IsDefaultModule { get { @@ -1862,8 +1933,8 @@ namespace Microsoft.Dafny { Contract.Invariant(cce.NonNullElements(TypeArgs)); } - public TopLevelDecl(IToken tok, string name, ModuleDefinition module, List typeArgs, Attributes attributes) - : base(tok, name, attributes) { + public TopLevelDecl(IToken tok, string name, ModuleDefinition module, List typeArgs, Attributes attributes, Declaration clonedFrom = null) + : base(tok, name, attributes, clonedFrom) { Contract.Requires(tok != null); Contract.Requires(name != null); Contract.Requires(cce.NonNullElements(typeArgs)); @@ -2116,7 +2187,7 @@ namespace Microsoft.Dafny { public List Destructors = new List(); // contents filled in during resolution; includes both implicit (not mentionable in source) and explicit destructors public DatatypeCtor(IToken tok, string name, [Captured] List formals, Attributes attributes) - : base(tok, name, attributes) { + : base(tok, name, attributes, null) { Contract.Requires(tok != null); Contract.Requires(name != null); Contract.Requires(cce.NonNullElements(formals)); @@ -2326,7 +2397,7 @@ namespace Microsoft.Dafny { public TopLevelDecl EnclosingClass; // filled in during resolution public MemberDecl RefinementBase; // filled in during the pre-resolution refinement transformation; null if the member is new here public MemberDecl(IToken tok, string name, bool hasStaticKeyword, bool isGhost, Attributes attributes) - : base(tok, name, attributes) { + : base(tok, name, attributes, null) { Contract.Requires(tok != null); Contract.Requires(name != null); HasStaticKeyword = hasStaticKeyword; @@ -2463,8 +2534,8 @@ namespace Microsoft.Dafny { Contract.Invariant(TheType != null && Name == TheType.Name); } - public OpaqueTypeDecl(IToken tok, string name, ModuleDefinition module, TypeParameter.EqualitySupportValue equalitySupport, List typeArgs, Attributes attributes) - : base(tok, name, module, typeArgs, attributes) { + public OpaqueTypeDecl(IToken tok, string name, ModuleDefinition module, TypeParameter.EqualitySupportValue equalitySupport, List typeArgs, Attributes attributes, Declaration clonedFrom = null) + : base(tok, name, module, typeArgs, attributes, clonedFrom) { Contract.Requires(tok != null); Contract.Requires(name != null); Contract.Requires(module != null); @@ -3063,7 +3134,7 @@ namespace Microsoft.Dafny { prefixPredCall.TypeArgumentSubstitutions = new Dictionary(); var old_to_new = new Dictionary(); for (int i = 0; i < this.TypeArgs.Count; i++) { - old_to_new[this.TypeArgs[i]] = this.PrefixPredicate.TypeArgs[i]; + old_to_new[this.TypeArgs[i]] = this.PrefixPredicate.TypeArgs[i]; } foreach (var p in fexp.TypeArgumentSubstitutions) { prefixPredCall.TypeArgumentSubstitutions[old_to_new[p.Key]] = p.Value; @@ -5578,8 +5649,8 @@ namespace Microsoft.Dafny { Contract.Invariant(cce.NonNullElements(Arguments)); Contract.Invariant(cce.NonNullElements(InferredTypeArgs)); Contract.Invariant( - Ctor == null || - InferredTypeArgs.Count == Ctor.EnclosingDatatype.TypeArgs.Count); + Ctor == null || + InferredTypeArgs.Count == Ctor.EnclosingDatatype.TypeArgs.Count); } public DatatypeValue(IToken tok, string datatypeName, string memberName, [Captured] List arguments) @@ -6009,10 +6080,10 @@ namespace Microsoft.Dafny { Function == null || TypeArgumentSubstitutions == null || Contract.ForAll( Function.TypeArgs, - a => TypeArgumentSubstitutions.ContainsKey(a)) && + a => TypeArgumentSubstitutions.ContainsKey(a)) && Contract.ForAll( TypeArgumentSubstitutions.Keys, - a => Function.TypeArgs.Contains(a) || Function.EnclosingClass.TypeArgs.Contains(a))); + a => Function.TypeArgs.Contains(a) || Function.EnclosingClass.TypeArgs.Contains(a))); } public Function Function; // filled in by resolution diff --git a/Source/Dafny/Makefile b/Source/Dafny/Makefile index 4c01c780..e8c0f5e0 100644 --- a/Source/Dafny/Makefile +++ b/Source/Dafny/Makefile @@ -4,8 +4,8 @@ # from http://boogiepartners.codeplex.com/. Update the FRAME_DIR variable to # point to whatever directory you install that into. # ############################################################################### -COCO_EXE_DIR = ..\..\..\boogiepartners\CocoRdownload -FRAME_DIR = ..\..\..\boogiepartners\CocoR\Modified +COCO_EXE_DIR = ..\..\..\boogie-partners\CocoRdownload +FRAME_DIR = ..\..\..\boogie-partners\CocoR\Modified COCO = $(COCO_EXE_DIR)\Coco.exe # "all" depends on 2 files, really (Parser.cs and Scanner.cs), but they diff --git a/Source/Dafny/Parser.cs b/Source/Dafny/Parser.cs index c4047819..a90e650a 100644 --- a/Source/Dafny/Parser.cs +++ b/Source/Dafny/Parser.cs @@ -72,10 +72,10 @@ public class Parser { public const int _star = 56; public const int _notIn = 57; public const int _ellipsis = 58; - public const int maxT = 137; + public const int maxT = 138; - const bool T = true; - const bool x = false; + const bool _T = true; + const bool _x = false; const int minErrDist = 2; public Scanner/*!*/ scanner; @@ -540,42 +540,42 @@ bool IsType(ref IToken pt) { } while (StartOf(1)) { switch (la.kind) { - case 60: case 61: case 63: { + case 60: case 61: case 64: { SubModuleDecl(defaultModule, out submodule); defaultModule.TopLevelDecls.Add(submodule); break; } - case 68: { + case 69: { ClassDecl(defaultModule, out c); defaultModule.TopLevelDecls.Add(c); break; } - case 74: case 75: { + case 75: case 76: { DatatypeDecl(defaultModule, out dt); defaultModule.TopLevelDecls.Add(dt); break; } - case 77: { + case 78: { NewtypeDecl(defaultModule, out td); defaultModule.TopLevelDecls.Add(td); break; } - case 78: { + case 79: { OtherTypeDecl(defaultModule, out td); defaultModule.TopLevelDecls.Add(td); break; } - case 79: { + case 80: { IteratorDecl(defaultModule, out iter); defaultModule.TopLevelDecls.Add(iter); break; } - case 70: { + case 71: { TraitDecl(defaultModule, out trait); defaultModule.TopLevelDecls.Add(trait); break; } - case 37: case 38: case 39: case 40: case 41: case 71: case 72: case 73: case 76: case 82: case 83: case 84: case 85: { + case 37: case 38: case 39: case 40: case 41: case 72: case 73: case 74: case 77: case 83: case 84: case 85: case 86: { ClassMemberDecl(membersDefaultClass, false, !DafnyOptions.O.AllowGlobals); break; } @@ -606,6 +606,7 @@ bool IsType(ref IToken pt) { ModuleDecl sm; submodule = null; // appease compiler bool isAbstract = false; + bool isExclusively = false; bool opened = false; if (la.kind == 60 || la.kind == 61) { @@ -618,51 +619,59 @@ bool IsType(ref IToken pt) { Attribute(ref attrs); } NoUSIdent(out id); - if (la.kind == 62) { - Get(); - QualifiedModuleName(out idRefined); + if (la.kind == 62 || la.kind == 63) { + if (la.kind == 62) { + Get(); + Expect(63); + QualifiedModuleName(out idRefined); + isExclusively = true; + } else { + Get(); + QualifiedModuleName(out idRefined); + isExclusively = false; + } } - module = new ModuleDefinition(id, id.val, isAbstract, false, idRefined == null ? null : idRefined, parent, attrs, false); + module = new ModuleDefinition(id, id.val, isAbstract, false, isExclusively, idRefined == null ? null : idRefined, parent, attrs, false, this); Expect(45); module.BodyStartTok = t; while (StartOf(1)) { switch (la.kind) { - case 60: case 61: case 63: { + case 60: case 61: case 64: { SubModuleDecl(module, out sm); module.TopLevelDecls.Add(sm); break; } - case 68: { + case 69: { ClassDecl(module, out c); module.TopLevelDecls.Add(c); break; } - case 70: { + case 71: { TraitDecl(module, out trait); module.TopLevelDecls.Add(trait); break; } - case 74: case 75: { + case 75: case 76: { DatatypeDecl(module, out dt); module.TopLevelDecls.Add(dt); break; } - case 77: { + case 78: { NewtypeDecl(module, out td); module.TopLevelDecls.Add(td); break; } - case 78: { + case 79: { OtherTypeDecl(module, out td); module.TopLevelDecls.Add(td); break; } - case 79: { + case 80: { IteratorDecl(module, out iter); module.TopLevelDecls.Add(iter); break; } - case 37: case 38: case 39: case 40: case 41: case 71: case 72: case 73: case 76: case 82: case 83: case 84: case 85: { + case 37: case 38: case 39: case 40: case 41: case 72: case 73: case 74: case 77: case 83: case 84: case 85: case 86: { ClassMemberDecl(namedModuleDefaultClassMembers, false, !DafnyOptions.O.AllowGlobals); break; } @@ -672,22 +681,22 @@ bool IsType(ref IToken pt) { module.BodyEndTok = t; module.TopLevelDecls.Add(new DefaultClassDecl(module, namedModuleDefaultClassMembers)); submodule = new LiteralModuleDecl(module, parent); - } else if (la.kind == 63) { + } else if (la.kind == 64) { Get(); - if (la.kind == 64) { + if (la.kind == 65) { Get(); opened = true; } NoUSIdent(out id); - if (la.kind == 65 || la.kind == 66) { - if (la.kind == 65) { + if (la.kind == 66 || la.kind == 67) { + if (la.kind == 66) { Get(); QualifiedModuleName(out idPath); submodule = new AliasModuleDecl(idPath, id, parent, opened); } else { Get(); QualifiedModuleName(out idPath); - if (la.kind == 67) { + if (la.kind == 68) { Get(); QualifiedModuleName(out idAssignment); } @@ -695,7 +704,7 @@ bool IsType(ref IToken pt) { } } if (la.kind == 27) { - while (!(la.kind == 0 || la.kind == 27)) {SynErr(138); Get();} + while (!(la.kind == 0 || la.kind == 27)) {SynErr(139); Get();} Get(); errors.Warning(t, "the semi-colon that used to terminate a sub-module declaration has been deprecated; in the new syntax, just leave off the semi-colon"); } @@ -705,7 +714,7 @@ bool IsType(ref IToken pt) { submodule = new AliasModuleDecl(idPath, id, parent, opened); } - } else SynErr(139); + } else SynErr(140); } void ClassDecl(ModuleDefinition/*!*/ module, out ClassDecl/*!*/ c) { @@ -719,8 +728,8 @@ bool IsType(ref IToken pt) { List members = new List(); IToken bodyStart; - while (!(la.kind == 0 || la.kind == 68)) {SynErr(140); Get();} - Expect(68); + while (!(la.kind == 0 || la.kind == 69)) {SynErr(141); Get();} + Expect(69); while (la.kind == 45) { Attribute(ref attrs); } @@ -728,7 +737,7 @@ bool IsType(ref IToken pt) { if (la.kind == 51) { GenericParameters(typeArgs); } - if (la.kind == 69) { + if (la.kind == 70) { Get(); Type(out trait); traits.Add(trait); @@ -760,13 +769,13 @@ bool IsType(ref IToken pt) { IToken bodyStart = Token.NoToken; // dummy assignment bool co = false; - while (!(la.kind == 0 || la.kind == 74 || la.kind == 75)) {SynErr(141); Get();} - if (la.kind == 74) { + while (!(la.kind == 0 || la.kind == 75 || la.kind == 76)) {SynErr(142); Get();} + if (la.kind == 75) { Get(); - } else if (la.kind == 75) { + } else if (la.kind == 76) { Get(); co = true; - } else SynErr(142); + } else SynErr(143); while (la.kind == 45) { Attribute(ref attrs); } @@ -774,7 +783,7 @@ bool IsType(ref IToken pt) { if (la.kind == 51) { GenericParameters(typeArgs); } - Expect(65); + Expect(66); bodyStart = t; DatatypeMemberDecl(ctors); while (la.kind == 23) { @@ -782,7 +791,7 @@ bool IsType(ref IToken pt) { DatatypeMemberDecl(ctors); } if (la.kind == 27) { - while (!(la.kind == 0 || la.kind == 27)) {SynErr(143); Get();} + while (!(la.kind == 0 || la.kind == 27)) {SynErr(144); Get();} Get(); errors.Warning(t, "the semi-colon that used to terminate a (co)datatype declaration has been deprecated; in the new syntax, just leave off the semi-colon"); } @@ -803,12 +812,12 @@ bool IsType(ref IToken pt) { Type baseType = null; Expression wh; - Expect(77); + Expect(78); while (la.kind == 45) { Attribute(ref attrs); } NoUSIdent(out id); - Expect(65); + Expect(66); if (IsIdentColonOrBar()) { NoUSIdent(out bvId); if (la.kind == 21) { @@ -822,7 +831,7 @@ bool IsType(ref IToken pt) { } else if (StartOf(3)) { Type(out baseType); td = new NewtypeDecl(theVerifyThisFile ? id : new IncludeToken(id), id.val, module, baseType, attrs); - } else SynErr(144); + } else SynErr(145); } void OtherTypeDecl(ModuleDefinition module, out TopLevelDecl td) { @@ -833,7 +842,7 @@ bool IsType(ref IToken pt) { td = null; Type ty; - Expect(78); + Expect(79); while (la.kind == 45) { Attribute(ref attrs); } @@ -850,18 +859,18 @@ bool IsType(ref IToken pt) { if (la.kind == 51) { GenericParameters(typeArgs); } - if (la.kind == 65) { + if (la.kind == 66) { Get(); Type(out ty); td = new TypeSynonymDecl(id, id.val, typeArgs, module, ty, attrs); } - } else SynErr(145); + } else SynErr(146); if (td == null) { td = new OpaqueTypeDecl(id, id.val, module, eqSupport, typeArgs, attrs); } if (la.kind == 27) { - while (!(la.kind == 0 || la.kind == 27)) {SynErr(146); Get();} + while (!(la.kind == 0 || la.kind == 27)) {SynErr(147); Get();} Get(); errors.Warning(t, "the semi-colon that used to terminate an opaque-type declaration has been deprecated; in the new syntax, just leave off the semi-colon"); } @@ -890,8 +899,8 @@ bool IsType(ref IToken pt) { IToken bodyStart = Token.NoToken; IToken bodyEnd = Token.NoToken; - while (!(la.kind == 0 || la.kind == 79)) {SynErr(147); Get();} - Expect(79); + while (!(la.kind == 0 || la.kind == 80)) {SynErr(148); Get();} + Expect(80); while (la.kind == 45) { Attribute(ref attrs); } @@ -901,8 +910,8 @@ bool IsType(ref IToken pt) { GenericParameters(typeArgs); } Formals(true, true, ins); - if (la.kind == 80 || la.kind == 81) { - if (la.kind == 80) { + if (la.kind == 81 || la.kind == 82) { + if (la.kind == 81) { Get(); } else { Get(); @@ -913,7 +922,7 @@ bool IsType(ref IToken pt) { } else if (la.kind == 58) { Get(); signatureEllipsis = t; - } else SynErr(148); + } else SynErr(149); while (StartOf(5)) { IteratorSpec(reads, mod, decreases, req, ens, yieldReq, yieldEns, ref readsAttrs, ref modAttrs, ref decrAttrs); } @@ -940,8 +949,8 @@ bool IsType(ref IToken pt) { List members = new List(); IToken bodyStart; - while (!(la.kind == 0 || la.kind == 70)) {SynErr(149); Get();} - Expect(70); + while (!(la.kind == 0 || la.kind == 71)) {SynErr(150); Get();} + Expect(71); while (la.kind == 45) { Attribute(ref attrs); } @@ -968,11 +977,11 @@ bool IsType(ref IToken pt) { MemberModifiers mmod = new MemberModifiers(); IToken staticToken = null, protectedToken = null; - while (la.kind == 71 || la.kind == 72 || la.kind == 73) { - if (la.kind == 71) { + while (la.kind == 72 || la.kind == 73 || la.kind == 74) { + if (la.kind == 72) { Get(); mmod.IsGhost = true; - } else if (la.kind == 72) { + } else if (la.kind == 73) { Get(); mmod.IsStatic = true; staticToken = t; } else { @@ -980,7 +989,7 @@ bool IsType(ref IToken pt) { mmod.IsProtected = true; protectedToken = t; } } - if (la.kind == 76) { + if (la.kind == 77) { if (moduleLevelDecl) { SemErr(la, "fields are not allowed to be declared at the module level; instead, wrap the field in a 'class' declaration"); mmod.IsStatic = false; @@ -1008,7 +1017,7 @@ bool IsType(ref IToken pt) { MethodDecl(mmod, allowConstructors, out m); mm.Add(m); - } else SynErr(150); + } else SynErr(151); } void Attribute(ref Attributes attrs) { @@ -1093,8 +1102,8 @@ bool IsType(ref IToken pt) { Attributes attrs = null; IToken/*!*/ id; Type/*!*/ ty; - while (!(la.kind == 0 || la.kind == 76)) {SynErr(151); Get();} - Expect(76); + while (!(la.kind == 0 || la.kind == 77)) {SynErr(152); Get();} + Expect(77); if (mmod.IsStatic) { SemErr(t, "fields cannot be declared 'static'"); } while (la.kind == 45) { @@ -1131,7 +1140,7 @@ bool IsType(ref IToken pt) { if (la.kind == 37) { Get(); - if (la.kind == 82) { + if (la.kind == 83) { Get(); isFunctionMethod = true; } @@ -1151,11 +1160,11 @@ bool IsType(ref IToken pt) { } else if (la.kind == 58) { Get(); signatureEllipsis = t; - } else SynErr(152); + } else SynErr(153); } else if (la.kind == 38) { Get(); isPredicate = true; - if (la.kind == 82) { + if (la.kind == 83) { Get(); isFunctionMethod = true; } @@ -1182,7 +1191,7 @@ bool IsType(ref IToken pt) { } else if (la.kind == 58) { Get(); signatureEllipsis = t; - } else SynErr(153); + } else SynErr(154); } else if (la.kind == 39) { Get(); Expect(38); @@ -1205,7 +1214,7 @@ bool IsType(ref IToken pt) { } else if (la.kind == 58) { Get(); signatureEllipsis = t; - } else SynErr(154); + } else SynErr(155); } else if (la.kind == 41) { Get(); isCoPredicate = true; @@ -1227,8 +1236,8 @@ bool IsType(ref IToken pt) { } else if (la.kind == 58) { Get(); signatureEllipsis = t; - } else SynErr(155); - } else SynErr(156); + } else SynErr(156); + } else SynErr(157); decreases = isIndPredicate || isCoPredicate ? null : new List(); while (StartOf(9)) { FunctionSpec(reqs, reads, ens, decreases); @@ -1287,9 +1296,9 @@ bool IsType(ref IToken pt) { IToken bodyStart = Token.NoToken; IToken bodyEnd = Token.NoToken; - while (!(StartOf(10))) {SynErr(157); Get();} + while (!(StartOf(10))) {SynErr(158); Get();} switch (la.kind) { - case 82: { + case 83: { Get(); break; } @@ -1298,12 +1307,12 @@ bool IsType(ref IToken pt) { isLemma = true; break; } - case 83: { + case 84: { Get(); isCoLemma = true; break; } - case 84: { + case 85: { Get(); isCoLemma = true; errors.Warning(t, "the 'comethod' keyword has been deprecated; it has been renamed to 'colemma'"); @@ -1316,7 +1325,7 @@ bool IsType(ref IToken pt) { isIndLemma = true; break; } - case 85: { + case 86: { Get(); if (allowConstructor) { isConstructor = true; @@ -1326,7 +1335,7 @@ bool IsType(ref IToken pt) { break; } - default: SynErr(158); break; + default: SynErr(159); break; } keywordToken = t; if (isLemma) { @@ -1369,7 +1378,7 @@ bool IsType(ref IToken pt) { GenericParameters(typeArgs); } Formals(true, !mmod.IsGhost, ins); - if (la.kind == 81) { + if (la.kind == 82) { Get(); if (isConstructor) { SemErr(t, "constructors cannot have out-parameters"); } Formals(false, !mmod.IsGhost, outs); @@ -1377,7 +1386,7 @@ bool IsType(ref IToken pt) { } else if (la.kind == 58) { Get(); signatureEllipsis = t; - } else SynErr(159); + } else SynErr(160); while (StartOf(11)) { MethodSpec(req, mod, ens, dec, ref decAttrs, ref modAttrs); } @@ -1450,14 +1459,14 @@ bool IsType(ref IToken pt) { } else if (la.kind == 2) { Get(); id = t; - } else SynErr(160); + } else SynErr(161); Expect(21); Type(out ty); } void OldSemi() { if (la.kind == 27) { - while (!(la.kind == 0 || la.kind == 27)) {SynErr(161); Get();} + while (!(la.kind == 0 || la.kind == 27)) {SynErr(162); Get();} Get(); } } @@ -1480,7 +1489,7 @@ bool IsType(ref IToken pt) { Contract.Ensures(Contract.ValueAtReturn(out id)!=null); Contract.Ensures(Contract.ValueAtReturn(out ty)!=null); isGhost = false; - if (la.kind == 71) { + if (la.kind == 72) { Get(); if (allowGhostKeyword) { isGhost = true; } else { SemErr(t, "formal cannot be declared 'ghost' in this context"); } } @@ -1532,7 +1541,7 @@ bool IsType(ref IToken pt) { Contract.Ensures(Contract.ValueAtReturn(out ty)!=null); Contract.Ensures(Contract.ValueAtReturn(out identName)!=null); string name = null; id = Token.NoToken; ty = new BoolType()/*dummy*/; isGhost = false; - if (la.kind == 71) { + if (la.kind == 72) { Get(); isGhost = true; } @@ -1554,7 +1563,7 @@ bool IsType(ref IToken pt) { id = t; name = id.val; Expect(21); Type(out ty); - } else SynErr(162); + } else SynErr(163); if (name != null) { identName = name; } else { @@ -1742,7 +1751,7 @@ bool IsType(ref IToken pt) { ty = new UserDefinedType(e.tok, e); break; } - default: SynErr(163); break; + default: SynErr(164); break; } if (la.kind == 29) { Type t2; @@ -1763,7 +1772,7 @@ bool IsType(ref IToken pt) { void Formals(bool incoming, bool allowGhostKeyword, List formals) { Contract.Requires(cce.NonNullElements(formals)); IToken id; Type ty; bool isGhost; Expect(49); - if (la.kind == 1 || la.kind == 71) { + if (la.kind == 1 || la.kind == 72) { GIdentType(allowGhostKeyword, out id, out ty, out isGhost); formals.Add(new Formal(id, id.val, ty, incoming, isGhost)); while (la.kind == 22) { @@ -1781,7 +1790,7 @@ List/*!*/ yieldReq, List/*!* ref Attributes readsAttrs, ref Attributes modAttrs, ref Attributes decrAttrs) { Expression/*!*/ e; FrameExpression/*!*/ fe; bool isFree = false; bool isYield = false; Attributes ensAttrs = null; - while (!(StartOf(13))) {SynErr(164); Get();} + while (!(StartOf(13))) {SynErr(165); Get();} if (la.kind == 43) { Get(); while (IsAttribute()) { @@ -1809,13 +1818,13 @@ ref Attributes readsAttrs, ref Attributes modAttrs, ref Attributes decrAttrs) { } OldSemi(); } else if (StartOf(14)) { - if (la.kind == 86) { + if (la.kind == 87) { Get(); isFree = true; errors.Warning(t, "the 'free' keyword is soon to be deprecated"); } - if (la.kind == 88) { + if (la.kind == 89) { Get(); isYield = true; } @@ -1829,7 +1838,7 @@ ref Attributes readsAttrs, ref Attributes modAttrs, ref Attributes decrAttrs) { req.Add(new MaybeFreeExpression(e, isFree)); } - } else if (la.kind == 87) { + } else if (la.kind == 88) { Get(); while (IsAttribute()) { Attribute(ref ensAttrs); @@ -1842,7 +1851,7 @@ ref Attributes readsAttrs, ref Attributes modAttrs, ref Attributes decrAttrs) { ens.Add(new MaybeFreeExpression(e, isFree, ensAttrs)); } - } else SynErr(165); + } else SynErr(166); } else if (la.kind == 35) { Get(); while (IsAttribute()) { @@ -1850,7 +1859,7 @@ ref Attributes readsAttrs, ref Attributes modAttrs, ref Attributes decrAttrs) { } DecreasesList(decreases, false, false); OldSemi(); - } else SynErr(166); + } else SynErr(167); } void BlockStmt(out BlockStmt/*!*/ block, out IToken bodyStart, out IToken bodyEnd) { @@ -1872,7 +1881,7 @@ List/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo Contract.Requires(cce.NonNullElements(req)); Contract.Requires(cce.NonNullElements(mod)); Contract.Requires(cce.NonNullElements(ens)); Contract.Requires(cce.NonNullElements(decreases)); Expression/*!*/ e; FrameExpression/*!*/ fe; bool isFree = false; Attributes ensAttrs = null; - while (!(StartOf(16))) {SynErr(167); Get();} + while (!(StartOf(16))) {SynErr(168); Get();} if (la.kind == 42) { Get(); while (IsAttribute()) { @@ -1886,8 +1895,8 @@ List/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo mod.Add(fe); } OldSemi(); - } else if (la.kind == 44 || la.kind == 86 || la.kind == 87) { - if (la.kind == 86) { + } else if (la.kind == 44 || la.kind == 87 || la.kind == 88) { + if (la.kind == 87) { Get(); isFree = true; errors.Warning(t, "the 'free' keyword is soon to be deprecated"); @@ -1898,7 +1907,7 @@ List/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo Expression(out e, false, false); OldSemi(); req.Add(new MaybeFreeExpression(e, isFree)); - } else if (la.kind == 87) { + } else if (la.kind == 88) { Get(); while (IsAttribute()) { Attribute(ref ensAttrs); @@ -1906,7 +1915,7 @@ List/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo Expression(out e, false, false); OldSemi(); ens.Add(new MaybeFreeExpression(e, isFree, ensAttrs)); - } else SynErr(168); + } else SynErr(169); } else if (la.kind == 35) { Get(); while (IsAttribute()) { @@ -1914,7 +1923,7 @@ List/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo } DecreasesList(decreases, true, false); OldSemi(); - } else SynErr(169); + } else SynErr(170); } void FrameExpression(out FrameExpression fe, bool allowSemi, bool allowLambda) { @@ -1927,18 +1936,18 @@ List/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo if (StartOf(7)) { Expression(out e, allowSemi, allowLambda); feTok = e.tok; - if (la.kind == 89) { + if (la.kind == 90) { Get(); Ident(out id); fieldName = id.val; feTok = id; } fe = new FrameExpression(feTok, e, fieldName); - } else if (la.kind == 89) { + } else if (la.kind == 90) { Get(); Ident(out id); fieldName = id.val; fe = new FrameExpression(id, new ImplicitThisExpr(id), fieldName); - } else SynErr(170); + } else SynErr(171); } void DecreasesList(List decreases, bool allowWildcard, bool allowLambda) { @@ -1993,7 +2002,7 @@ List/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo Contract.Requires(cce.NonNullElements(reads)); Contract.Requires(decreases == null || cce.NonNullElements(decreases)); Expression/*!*/ e; FrameExpression/*!*/ fe; - while (!(StartOf(17))) {SynErr(171); Get();} + while (!(StartOf(17))) {SynErr(172); Get();} if (la.kind == 44) { Get(); Expression(out e, false, false); @@ -2009,7 +2018,7 @@ List/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo reads.Add(fe); } OldSemi(); - } else if (la.kind == 87) { + } else if (la.kind == 88) { Get(); Expression(out e, false, false); OldSemi(); @@ -2023,7 +2032,7 @@ List/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo DecreasesList(decreases, false, false); OldSemi(); - } else SynErr(172); + } else SynErr(173); } void FunctionBody(out Expression/*!*/ e, out IToken bodyStart, out IToken bodyEnd) { @@ -2042,7 +2051,7 @@ List/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo fe = new FrameExpression(t, new WildcardExpr(t), null); } else if (StartOf(18)) { FrameExpression(out fe, allowSemi, false); - } else SynErr(173); + } else SynErr(174); } void PossiblyWildExpression(out Expression e, bool allowLambda) { @@ -2053,7 +2062,7 @@ List/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo e = new WildcardExpr(t); } else if (StartOf(7)) { Expression(out e, false, allowLambda); - } else SynErr(174); + } else SynErr(175); } void Stmt(List/*!*/ ss) { @@ -2070,14 +2079,14 @@ List/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo IToken bodyStart, bodyEnd; int breakCount; - while (!(StartOf(19))) {SynErr(175); Get();} + while (!(StartOf(19))) {SynErr(176); Get();} switch (la.kind) { case 45: { BlockStmt(out bs, out bodyStart, out bodyEnd); s = bs; break; } - case 100: { + case 101: { AssertStmt(out s); break; } @@ -2085,31 +2094,31 @@ List/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo AssumeStmt(out s); break; } - case 101: { + case 102: { PrintStmt(out s); break; } - case 1: case 2: case 3: case 4: case 8: case 10: case 19: case 20: case 23: case 49: case 130: case 131: case 132: case 133: case 134: case 135: { + case 1: case 2: case 3: case 4: case 8: case 10: case 19: case 20: case 23: case 49: case 131: case 132: case 133: case 134: case 135: case 136: { UpdateStmt(out s); break; } - case 71: case 76: { + case 72: case 77: { VarDeclStatement(out s); break; } - case 97: { + case 98: { IfStmt(out s); break; } - case 98: { + case 99: { WhileStmt(out s); break; } - case 99: { + case 100: { MatchStmt(out s); break; } - case 102: case 103: { + case 103: case 104: { ForallStmt(out s); break; } @@ -2117,11 +2126,11 @@ List/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo CalcStmt(out s); break; } - case 104: { + case 105: { ModifyStmt(out s); break; } - case 90: { + case 91: { Get(); x = t; NoUSIdent(out id); @@ -2130,24 +2139,24 @@ List/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo s.Labels = new LList -public static int Parse (string/*!*/ s, string/*!*/ filename, ModuleDecl module, BuiltIns builtIns, bool verifyThisFile=true) { +public static int Parse (string/*!*/ s, string/*!*/ fullFilename, string/*!*/ filename, ModuleDecl module, BuiltIns builtIns, bool verifyThisFile=true) { Contract.Requires(s != null); Contract.Requires(filename != null); Contract.Requires(module != null); Errors errors = new Errors(); - return Parse(s, filename, module, builtIns, errors, verifyThisFile); + return Parse(s, fullFilename, filename, module, builtIns, errors, verifyThisFile); } /// /// Parses top-level things (modules, classes, datatypes, class members) @@ -68,15 +68,15 @@ public static int Parse (string/*!*/ s, string/*!*/ filename, ModuleDecl module, /// Returns the number of parsing errors encountered. /// Note: first initialize the Scanner with the given Errors sink. /// -public static int Parse (string/*!*/ s, string/*!*/ filename, ModuleDecl module, BuiltIns builtIns, - Errors/*!*/ errors, bool verifyThisFile=true) { +public static int Parse (string/*!*/ s, string/*!*/ fullFilename, string/*!*/ filename, ModuleDecl module, + BuiltIns builtIns, Errors/*!*/ errors, bool verifyThisFile=true) { Contract.Requires(s != null); Contract.Requires(filename != null); Contract.Requires(module != null); Contract.Requires(errors != null); byte[]/*!*/ buffer = cce.NonNull( UTF8Encoding.Default.GetBytes(s)); MemoryStream ms = new MemoryStream(buffer,false); - Scanner scanner = new Scanner(ms, errors, filename); + Scanner scanner = new Scanner(ms, errors, fullFilename, filename); Parser parser = new Parser(scanner, errors, module, builtIns, verifyThisFile); parser.Parse(); return parser.errors.count; @@ -506,7 +506,7 @@ Dafny Contract.Assert(defaultModule != null); .) { "include" stringToken (. { - string parsedFile = t.filename; + string parsedFile = scanner.FullFilename; bool isVerbatimString; string includedFile = Util.RemoveParsedStringQuotes(t.val, out isVerbatimString); includedFile = Util.RemoveEscaping(includedFile, isVerbatimString); diff --git a/Source/Dafny/Parser.cs b/Source/Dafny/Parser.cs index d50a4dd6..dae1b95e 100644 --- a/Source/Dafny/Parser.cs +++ b/Source/Dafny/Parser.cs @@ -112,11 +112,11 @@ public static int Parse (string/*!*/ filename, ModuleDecl module, BuiltIns built string s; if (filename == "stdin.dfy") { s = Microsoft.Boogie.ParserHelper.Fill(System.Console.In, new List()); - return Parse(s, filename, module, builtIns, errors, verifyThisFile); + return Parse(s, filename, filename, module, builtIns, errors, verifyThisFile); } else { using (System.IO.StreamReader reader = new System.IO.StreamReader(filename)) { s = Microsoft.Boogie.ParserHelper.Fill(reader, new List()); - return Parse(s, DafnyOptions.Clo.UseBaseNameForFileName ? Path.GetFileName(filename) : filename, module, builtIns, errors, verifyThisFile); + return Parse(s, filename, DafnyOptions.Clo.UseBaseNameForFileName ? Path.GetFileName(filename) : filename, module, builtIns, errors, verifyThisFile); } } } @@ -126,12 +126,12 @@ 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/*!*/ filename, ModuleDecl module, BuiltIns builtIns, bool verifyThisFile=true) { +public static int Parse (string/*!*/ s, string/*!*/ fullFilename, string/*!*/ filename, ModuleDecl module, BuiltIns builtIns, bool verifyThisFile=true) { Contract.Requires(s != null); Contract.Requires(filename != null); Contract.Requires(module != null); Errors errors = new Errors(); - return Parse(s, filename, module, builtIns, errors, verifyThisFile); + return Parse(s, fullFilename, filename, module, builtIns, errors, verifyThisFile); } /// /// Parses top-level things (modules, classes, datatypes, class members) @@ -139,15 +139,15 @@ public static int Parse (string/*!*/ s, string/*!*/ filename, ModuleDecl module, /// Returns the number of parsing errors encountered. /// Note: first initialize the Scanner with the given Errors sink. /// -public static int Parse (string/*!*/ s, string/*!*/ filename, ModuleDecl module, BuiltIns builtIns, - Errors/*!*/ errors, bool verifyThisFile=true) { +public static int Parse (string/*!*/ s, string/*!*/ fullFilename, string/*!*/ filename, ModuleDecl module, + BuiltIns builtIns, Errors/*!*/ errors, bool verifyThisFile=true) { Contract.Requires(s != null); Contract.Requires(filename != null); Contract.Requires(module != null); Contract.Requires(errors != null); byte[]/*!*/ buffer = cce.NonNull( UTF8Encoding.Default.GetBytes(s)); MemoryStream ms = new MemoryStream(buffer,false); - Scanner scanner = new Scanner(ms, errors, filename); + Scanner scanner = new Scanner(ms, errors, fullFilename, filename); Parser parser = new Parser(scanner, errors, module, builtIns, verifyThisFile); parser.Parse(); return parser.errors.count; @@ -536,7 +536,7 @@ bool IsType(ref IToken pt) { Get(); Expect(20); { - string parsedFile = t.filename; + string parsedFile = scanner.FullFilename; bool isVerbatimString; string includedFile = Util.RemoveParsedStringQuotes(t.val, out isVerbatimString); includedFile = Util.RemoveEscaping(includedFile, isVerbatimString); diff --git a/Source/Dafny/Scanner.cs b/Source/Dafny/Scanner.cs index 325a2f2c..a73f510d 100644 --- a/Source/Dafny/Scanner.cs +++ b/Source/Dafny/Scanner.cs @@ -224,6 +224,7 @@ public class Scanner { Contract.Invariant(pt != null); Contract.Invariant(tval != null); Contract.Invariant(Filename != null); + Contract.Invariant(FullFilename != null); Contract.Invariant(errorHandler != null); } @@ -258,6 +259,8 @@ public class Scanner { private string/*!*/ Filename; private Errors/*!*/ errorHandler; + internal string/*!*/ FullFilename { get; private set; } + static Scanner() { start = new Hashtable(128); for (int i = 63; i <= 63; ++i) start[i] = 1; @@ -310,7 +313,7 @@ public class Scanner { } // [NotDelayed] - public Scanner (string/*!*/ fileName, Errors/*!*/ errorHandler, bool useBaseName = false) : base() { + public Scanner (string/*!*/ fullFilename, string/*!*/ fileName, Errors/*!*/ errorHandler, bool useBaseName = false) : base() { Contract.Requires(fileName != null); Contract.Requires(errorHandler != null); this.errorHandler = errorHandler; @@ -319,6 +322,7 @@ public class Scanner { try { Stream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read); this._buffer = new Buffer(stream, false); + this.FullFilename = fullFilename; Filename = useBaseName? GetBaseName(fileName): fileName; Init(); } catch (IOException) { @@ -327,7 +331,7 @@ public class Scanner { } // [NotDelayed] - public Scanner (Stream/*!*/ s, Errors/*!*/ errorHandler, string/*!*/ fileName, bool useBaseName = false) : base() { + 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); @@ -335,6 +339,7 @@ public class Scanner { t = new Token(); // dummy because t is a non-null field this._buffer = new Buffer(s, true); this.errorHandler = errorHandler; + this.FullFilename = fullFilename; this.Filename = useBaseName? GetBaseName(fileName) : fileName; Init(); } -- 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/Dafny/Scanner.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 e07d86d6cc4423703dbfb479f09b44c80f877ef9 Mon Sep 17 00:00:00 2001 From: leino Date: Sat, 3 Oct 2015 02:40:41 -0700 Subject: Parsing and pretty printing of the new "existential guards" of the two kinds of "if" statements. --- Source/Dafny/Cloner.cs | 4 +- Source/Dafny/Dafny.atg | 64 +- Source/Dafny/DafnyAst.cs | 12 +- Source/Dafny/Parser.cs | 1268 ++++++++++++++++-------------- Source/Dafny/Printer.cs | 60 +- Source/Dafny/RefinementTransformer.cs | 8 +- Source/Dafny/Resolver.cs | 2 +- Source/Dafny/Rewriter.cs | 2 +- Source/Dafny/Scanner.cs | 264 +++---- Source/Dafny/Translator.cs | 4 +- Test/dafny0/ExistentialGuards.dfy | 89 +++ Test/dafny0/ExistentialGuards.dfy.expect | 94 +++ Test/dafny0/Simple.dfy | 27 + Test/dafny0/Simple.dfy.expect | 29 + 14 files changed, 1137 insertions(+), 790 deletions(-) create mode 100644 Test/dafny0/ExistentialGuards.dfy create mode 100644 Test/dafny0/ExistentialGuards.dfy.expect (limited to 'Source/Dafny/Scanner.cs') diff --git a/Source/Dafny/Cloner.cs b/Source/Dafny/Cloner.cs index 45d8a2c9..9a93a340 100644 --- a/Source/Dafny/Cloner.cs +++ b/Source/Dafny/Cloner.cs @@ -531,7 +531,7 @@ namespace Microsoft.Dafny } else if (stmt is IfStmt) { var s = (IfStmt)stmt; - r = new IfStmt(Tok(s.Tok), Tok(s.EndTok), CloneExpr(s.Guard), CloneBlockStmt(s.Thn), CloneStmt(s.Els)); + r = new IfStmt(Tok(s.Tok), Tok(s.EndTok), s.IsExistentialGuard, CloneExpr(s.Guard), CloneBlockStmt(s.Thn), CloneStmt(s.Els)); } else if (stmt is AlternativeStmt) { var s = (AlternativeStmt)stmt; @@ -631,7 +631,7 @@ namespace Microsoft.Dafny } public GuardedAlternative CloneGuardedAlternative(GuardedAlternative alt) { - return new GuardedAlternative(Tok(alt.Tok), CloneExpr(alt.Guard), alt.Body.ConvertAll(CloneStmt)); + return new GuardedAlternative(Tok(alt.Tok), alt.IsExistentialGuard, CloneExpr(alt.Guard), alt.Body.ConvertAll(CloneStmt)); } public Function CloneFunction(Function f, string newName = null) { diff --git a/Source/Dafny/Dafny.atg b/Source/Dafny/Dafny.atg index 954448af..66dff8a2 100644 --- a/Source/Dafny/Dafny.atg +++ b/Source/Dafny/Dafny.atg @@ -104,6 +104,25 @@ bool IsAlternative() { return la.kind == _lbrace && x.kind == _case; } +// an existential guard starts with an identifier and is then followed by +// * a colon (if the first identifier is given an explicit type), +// * a comma (if there's a list a bound variables and the first one is not given an explicit type), +// * a start-attribute (if there's one bound variable and it is not given an explicit type and there are attributes), or +// * a bored smiley (if there's one bound variable and it is not given an explicit type). +bool IsExistentialGuard() { + scanner.ResetPeek(); + if (la.kind == _ident) { + Token x = scanner.Peek(); + if (x.kind == _colon || x.kind == _comma || x.kind == _boredSmiley) { + return true; + } else if (x.kind == _lbrace) { + x = scanner.Peek(); + return x.kind == _colon; + } + } + return false; +} + bool IsLoopSpec() { return la.kind == _invariant | la.kind == _decreases | la.kind == _modifies; } @@ -456,6 +475,7 @@ TOKENS comma = ','. verticalbar = '|'. doublecolon = "::". + boredSmiley = ":|". bullet = '\u2022'. dot = '.'. semi = ';'. @@ -1651,7 +1671,7 @@ VarDeclStatement<.out Statement/*!*/ s.> . IfStmt = (. Contract.Ensures(Contract.ValueAtReturn(out ifStmt) != null); IToken/*!*/ x; - Expression guard = null; IToken guardEllipsis = null; + Expression guard = null; IToken guardEllipsis = null; bool isExistentialGuard = false; BlockStmt/*!*/ thn; BlockStmt/*!*/ bs; Statement/*!*/ s; @@ -1663,11 +1683,13 @@ IfStmt "if" (. x = t; .) ( IF(IsAlternative()) - AlternativeBlock + AlternativeBlock (. ifStmt = new AlternativeStmt(x, endTok, alternatives); .) | - ( Guard - | "..." (. guardEllipsis = t; .) + ( IF(IsExistentialGuard()) + ExistentialGuard (. isExistentialGuard = true; .) + | Guard + | "..." (. guardEllipsis = t; .) ) BlockStmt (. endTok = thn.EndTok; .) [ "else" @@ -1676,26 +1698,29 @@ IfStmt ) ] (. if (guardEllipsis != null) { - ifStmt = new SkeletonStatement(new IfStmt(x, endTok, guard, thn, els), guardEllipsis, null); + ifStmt = new SkeletonStatement(new IfStmt(x, endTok, isExistentialGuard, guard, thn, els), guardEllipsis, null); } else { - ifStmt = new IfStmt(x, endTok, guard, thn, els); + ifStmt = new IfStmt(x, endTok, isExistentialGuard, guard, thn, els); } .) ) . -AlternativeBlock<.out List alternatives, out IToken endTok.> +AlternativeBlock<.bool allowExistentialGuards, out List alternatives, out IToken endTok.> = (. alternatives = new List(); IToken x; - Expression e; + Expression e; bool isExistentialGuard; List body; .) "{" - { "case" (. x = t; .) - Expression // NB: don't allow lambda here + { "case" (. x = t; isExistentialGuard = false; e = dummyExpr; .) + ( IF(allowExistentialGuards && IsExistentialGuard()) + ExistentialGuard (. isExistentialGuard = true; .) // NB: don't allow lambda here + | Expression // NB: don't allow lambda here + ) "=>" (. body = new List(); .) { Stmt } - (. alternatives.Add(new GuardedAlternative(x, e, body)); .) + (. alternatives.Add(new GuardedAlternative(x, isExistentialGuard, e, body)); .) } "}" (. endTok = t; .) . @@ -1719,7 +1744,7 @@ WhileStmt ( IF(IsLoopSpec() || IsAlternative()) { LoopSpec } - AlternativeBlock + AlternativeBlock (. stmt = new AlternativeLoopStmt(x, endTok, invariants, new Specification(decreases, decAttrs), new Specification(mod, modAttrs), alternatives); .) | ( Guard (. Contract.Assume(guard == null || cce.Owner.None(guard)); .) @@ -1799,6 +1824,21 @@ Guard /* null represents demonic-choice */ | Expression (. e = ee; .) ) . +ExistentialGuard += (. var bvars = new List(); + BoundVar bv; IToken x; + Attributes attrs = null; + Expression body; + .) + IdentTypeOptional (. bvars.Add(bv); x = bv.tok; .) + { "," + IdentTypeOptional (. bvars.Add(bv); .) + } + { Attribute } + ":|" + Expression + (. e = new ExistsExpr(x, bvars, null, body, attrs); .) + . MatchStmt = (. Contract.Ensures(Contract.ValueAtReturn(out s) != null); Token x; Expression/*!*/ e; MatchCaseStmt/*!*/ c; diff --git a/Source/Dafny/DafnyAst.cs b/Source/Dafny/DafnyAst.cs index 4fc48f2f..64af1425 100644 --- a/Source/Dafny/DafnyAst.cs +++ b/Source/Dafny/DafnyAst.cs @@ -4411,20 +4411,24 @@ namespace Microsoft.Dafny { } public class IfStmt : Statement { + public readonly bool IsExistentialGuard; public readonly Expression Guard; public readonly BlockStmt Thn; public readonly Statement Els; [ContractInvariantMethod] void ObjectInvariant() { + Contract.Invariant(!IsExistentialGuard || (Guard is ExistsExpr && ((ExistsExpr)Guard).Range == null)); Contract.Invariant(Thn != null); Contract.Invariant(Els == null || Els is BlockStmt || Els is IfStmt || Els is SkeletonStatement); } - public IfStmt(IToken tok, IToken endTok, Expression guard, BlockStmt thn, Statement els) + public IfStmt(IToken tok, IToken endTok, bool isExistentialGuard, Expression guard, BlockStmt thn, Statement els) : base(tok, endTok) { Contract.Requires(tok != null); Contract.Requires(endTok != null); + Contract.Requires(!isExistentialGuard || (guard is ExistsExpr && ((ExistsExpr)guard).Range == null)); Contract.Requires(thn != null); Contract.Requires(els == null || els is BlockStmt || els is IfStmt || els is SkeletonStatement); + this.IsExistentialGuard = isExistentialGuard; this.Guard = guard; this.Thn = thn; this.Els = els; @@ -4450,20 +4454,24 @@ namespace Microsoft.Dafny { public class GuardedAlternative { public readonly IToken Tok; + public readonly bool IsExistentialGuard; public readonly Expression Guard; public readonly List Body; [ContractInvariantMethod] void ObjectInvariant() { Contract.Invariant(Tok != null); Contract.Invariant(Guard != null); + Contract.Invariant(!IsExistentialGuard || (Guard is ExistsExpr && ((ExistsExpr)Guard).Range == null)); Contract.Invariant(Body != null); } - public GuardedAlternative(IToken tok, Expression guard, List body) + public GuardedAlternative(IToken tok, bool isExistentialGuard, Expression guard, List body) { Contract.Requires(tok != null); Contract.Requires(guard != null); + Contract.Requires(!isExistentialGuard || (guard is ExistsExpr && ((ExistsExpr)guard).Range == null)); Contract.Requires(body != null); this.Tok = tok; + this.IsExistentialGuard = isExistentialGuard; this.Guard = guard; this.Body = body; } diff --git a/Source/Dafny/Parser.cs b/Source/Dafny/Parser.cs index 7dafb572..c79c1051 100644 --- a/Source/Dafny/Parser.cs +++ b/Source/Dafny/Parser.cs @@ -38,40 +38,41 @@ public class Parser { public const int _comma = 22; public const int _verticalbar = 23; public const int _doublecolon = 24; - public const int _bullet = 25; - public const int _dot = 26; - public const int _semi = 27; - public const int _darrow = 28; - public const int _arrow = 29; - public const int _assume = 30; - public const int _calc = 31; - public const int _case = 32; - public const int _then = 33; - public const int _else = 34; - public const int _decreases = 35; - public const int _invariant = 36; - public const int _function = 37; - public const int _predicate = 38; - public const int _inductive = 39; - public const int _lemma = 40; - public const int _copredicate = 41; - public const int _modifies = 42; - public const int _reads = 43; - public const int _requires = 44; - public const int _lbrace = 45; - public const int _rbrace = 46; - public const int _lbracket = 47; - public const int _rbracket = 48; - public const int _openparen = 49; - public const int _closeparen = 50; - public const int _openAngleBracket = 51; - public const int _closeAngleBracket = 52; - public const int _eq = 53; - public const int _neq = 54; - public const int _neqAlt = 55; - public const int _star = 56; - public const int _notIn = 57; - public const int _ellipsis = 58; + public const int _boredSmiley = 25; + public const int _bullet = 26; + public const int _dot = 27; + public const int _semi = 28; + public const int _darrow = 29; + public const int _arrow = 30; + public const int _assume = 31; + public const int _calc = 32; + public const int _case = 33; + public const int _then = 34; + public const int _else = 35; + public const int _decreases = 36; + public const int _invariant = 37; + public const int _function = 38; + public const int _predicate = 39; + public const int _inductive = 40; + public const int _lemma = 41; + public const int _copredicate = 42; + public const int _modifies = 43; + public const int _reads = 44; + public const int _requires = 45; + public const int _lbrace = 46; + public const int _rbrace = 47; + public const int _lbracket = 48; + public const int _rbracket = 49; + public const int _openparen = 50; + public const int _closeparen = 51; + public const int _openAngleBracket = 52; + public const int _closeAngleBracket = 53; + public const int _eq = 54; + public const int _neq = 55; + public const int _neqAlt = 56; + public const int _star = 57; + public const int _notIn = 58; + public const int _ellipsis = 59; public const int maxT = 138; const bool _T = true; @@ -175,6 +176,25 @@ bool IsAlternative() { return la.kind == _lbrace && x.kind == _case; } +// an existential guard starts with an identifier and is then followed by +// * a colon (if the first identifier is given an explicit type), +// * a comma (if there's a list a bound variables and the first one is not given an explicit type), +// * a start-attribute (if there's one bound variable and it is not given an explicit type and there are attributes), or +// * a bored smiley (if there's one bound variable and it is not given an explicit type). +bool IsExistentialGuard() { + scanner.ResetPeek(); + if (la.kind == _ident) { + Token x = scanner.Peek(); + if (x.kind == _colon || x.kind == _comma || x.kind == _boredSmiley) { + return true; + } else if (x.kind == _lbrace) { + x = scanner.Peek(); + return x.kind == _colon; + } + } + return false; +} + bool IsLoopSpec() { return la.kind == _invariant | la.kind == _decreases | la.kind == _modifies; } @@ -532,7 +552,7 @@ bool IsType(ref IToken pt) { TraitDecl/*!*/ trait; Contract.Assert(defaultModule != null); - while (la.kind == 59) { + while (la.kind == 60) { Get(); Expect(20); { @@ -552,42 +572,42 @@ bool IsType(ref IToken pt) { } while (StartOf(1)) { switch (la.kind) { - case 60: case 61: case 64: { + case 61: case 62: case 65: { SubModuleDecl(defaultModule, out submodule); defaultModule.TopLevelDecls.Add(submodule); break; } - case 69: { + case 70: { ClassDecl(defaultModule, out c); defaultModule.TopLevelDecls.Add(c); break; } - case 75: case 76: { + case 76: case 77: { DatatypeDecl(defaultModule, out dt); defaultModule.TopLevelDecls.Add(dt); break; } - case 78: { + case 79: { NewtypeDecl(defaultModule, out td); defaultModule.TopLevelDecls.Add(td); break; } - case 79: { + case 80: { OtherTypeDecl(defaultModule, out td); defaultModule.TopLevelDecls.Add(td); break; } - case 80: { + case 81: { IteratorDecl(defaultModule, out iter); defaultModule.TopLevelDecls.Add(iter); break; } - case 71: { + case 72: { TraitDecl(defaultModule, out trait); defaultModule.TopLevelDecls.Add(trait); break; } - case 37: case 38: case 39: case 40: case 41: case 72: case 73: case 74: case 77: case 83: case 84: case 85: case 86: { + case 38: case 39: case 40: case 41: case 42: case 73: case 74: case 75: case 78: case 84: case 85: case 86: case 87: { ClassMemberDecl(membersDefaultClass, false, !DafnyOptions.O.AllowGlobals, false); break; } @@ -621,20 +641,20 @@ bool IsType(ref IToken pt) { bool isExclusively = false; bool opened = false; - if (la.kind == 60 || la.kind == 61) { - if (la.kind == 60) { + if (la.kind == 61 || la.kind == 62) { + if (la.kind == 61) { Get(); isAbstract = true; } - Expect(61); - while (la.kind == 45) { + Expect(62); + while (la.kind == 46) { Attribute(ref attrs); } NoUSIdent(out id); - if (la.kind == 62 || la.kind == 63) { - if (la.kind == 62) { + if (la.kind == 63 || la.kind == 64) { + if (la.kind == 63) { Get(); - Expect(63); + Expect(64); QualifiedModuleName(out idRefined); isExclusively = true; } else { @@ -644,79 +664,79 @@ bool IsType(ref IToken pt) { } } module = new ModuleDefinition(id, id.val, isAbstract, false, isExclusively, idRefined == null ? null : idRefined, parent, attrs, false, this); - Expect(45); + Expect(46); module.BodyStartTok = t; while (StartOf(1)) { switch (la.kind) { - case 60: case 61: case 64: { + case 61: case 62: case 65: { SubModuleDecl(module, out sm); module.TopLevelDecls.Add(sm); break; } - case 69: { + case 70: { ClassDecl(module, out c); module.TopLevelDecls.Add(c); break; } - case 71: { + case 72: { TraitDecl(module, out trait); module.TopLevelDecls.Add(trait); break; } - case 75: case 76: { + case 76: case 77: { DatatypeDecl(module, out dt); module.TopLevelDecls.Add(dt); break; } - case 78: { + case 79: { NewtypeDecl(module, out td); module.TopLevelDecls.Add(td); break; } - case 79: { + case 80: { OtherTypeDecl(module, out td); module.TopLevelDecls.Add(td); break; } - case 80: { + case 81: { IteratorDecl(module, out iter); module.TopLevelDecls.Add(iter); break; } - case 37: case 38: case 39: case 40: case 41: case 72: case 73: case 74: case 77: case 83: case 84: case 85: case 86: { + case 38: case 39: case 40: case 41: case 42: case 73: case 74: case 75: case 78: case 84: case 85: case 86: case 87: { ClassMemberDecl(namedModuleDefaultClassMembers, false, !DafnyOptions.O.AllowGlobals, DafnyOptions.O.IronDafny && isAbstract); break; } } } - Expect(46); + Expect(47); module.BodyEndTok = t; module.TopLevelDecls.Add(new DefaultClassDecl(module, namedModuleDefaultClassMembers)); submodule = new LiteralModuleDecl(module, parent); - } else if (la.kind == 64) { + } else if (la.kind == 65) { Get(); - if (la.kind == 65) { + if (la.kind == 66) { Get(); opened = true; } NoUSIdent(out id); - if (la.kind == 66 || la.kind == 67) { - if (la.kind == 66) { + if (la.kind == 67 || la.kind == 68) { + if (la.kind == 67) { Get(); QualifiedModuleName(out idPath); submodule = new AliasModuleDecl(idPath, id, parent, opened); } else { Get(); QualifiedModuleName(out idPath); - if (la.kind == 68) { + if (la.kind == 69) { Get(); QualifiedModuleName(out idAssignment); } submodule = new ModuleFacadeDecl(idPath, id, parent, idAssignment, opened); } } - if (la.kind == 27) { - while (!(la.kind == 0 || la.kind == 27)) {SynErr(139); Get();} + if (la.kind == 28) { + while (!(la.kind == 0 || la.kind == 28)) {SynErr(139); Get();} Get(); errors.Warning(t, "the semi-colon that used to terminate a sub-module declaration has been deprecated; in the new syntax, just leave off the semi-colon"); } @@ -740,16 +760,16 @@ bool IsType(ref IToken pt) { List members = new List(); IToken bodyStart; - while (!(la.kind == 0 || la.kind == 69)) {SynErr(141); Get();} - Expect(69); - while (la.kind == 45) { + while (!(la.kind == 0 || la.kind == 70)) {SynErr(141); Get();} + Expect(70); + while (la.kind == 46) { Attribute(ref attrs); } NoUSIdent(out id); - if (la.kind == 51) { + if (la.kind == 52) { GenericParameters(typeArgs); } - if (la.kind == 70) { + if (la.kind == 71) { Get(); Type(out trait); traits.Add(trait); @@ -759,12 +779,12 @@ bool IsType(ref IToken pt) { traits.Add(trait); } } - Expect(45); + Expect(46); bodyStart = t; while (StartOf(2)) { ClassMemberDecl(members, true, false, false); } - Expect(46); + Expect(47); c = new ClassDecl(id, id.val, module, typeArgs, members, attrs, traits); c.BodyStartTok = bodyStart; c.BodyEndTok = t; @@ -781,29 +801,29 @@ bool IsType(ref IToken pt) { IToken bodyStart = Token.NoToken; // dummy assignment bool co = false; - while (!(la.kind == 0 || la.kind == 75 || la.kind == 76)) {SynErr(142); Get();} - if (la.kind == 75) { + while (!(la.kind == 0 || la.kind == 76 || la.kind == 77)) {SynErr(142); Get();} + if (la.kind == 76) { Get(); - } else if (la.kind == 76) { + } else if (la.kind == 77) { Get(); co = true; } else SynErr(143); - while (la.kind == 45) { + while (la.kind == 46) { Attribute(ref attrs); } NoUSIdent(out id); - if (la.kind == 51) { + if (la.kind == 52) { GenericParameters(typeArgs); } - Expect(66); + Expect(67); bodyStart = t; DatatypeMemberDecl(ctors); while (la.kind == 23) { Get(); DatatypeMemberDecl(ctors); } - if (la.kind == 27) { - while (!(la.kind == 0 || la.kind == 27)) {SynErr(144); Get();} + if (la.kind == 28) { + while (!(la.kind == 0 || la.kind == 28)) {SynErr(144); Get();} Get(); errors.Warning(t, "the semi-colon that used to terminate a (co)datatype declaration has been deprecated; in the new syntax, just leave off the semi-colon"); } @@ -824,12 +844,12 @@ bool IsType(ref IToken pt) { Type baseType = null; Expression wh; - Expect(78); - while (la.kind == 45) { + Expect(79); + while (la.kind == 46) { Attribute(ref attrs); } NoUSIdent(out id); - Expect(66); + Expect(67); if (IsIdentColonOrBar()) { NoUSIdent(out bvId); if (la.kind == 21) { @@ -854,24 +874,24 @@ bool IsType(ref IToken pt) { td = null; Type ty; - Expect(79); - while (la.kind == 45) { + Expect(80); + while (la.kind == 46) { Attribute(ref attrs); } NoUSIdent(out id); - if (la.kind == 49) { + if (la.kind == 50) { Get(); - Expect(53); - Expect(50); + Expect(54); + Expect(51); eqSupport = TypeParameter.EqualitySupportValue.Required; - if (la.kind == 51) { + if (la.kind == 52) { GenericParameters(typeArgs); } } else if (StartOf(4)) { - if (la.kind == 51) { + if (la.kind == 52) { GenericParameters(typeArgs); } - if (la.kind == 66) { + if (la.kind == 67) { Get(); Type(out ty); td = new TypeSynonymDecl(id, id.val, typeArgs, module, ty, attrs); @@ -881,8 +901,8 @@ bool IsType(ref IToken pt) { td = new OpaqueTypeDecl(id, id.val, module, eqSupport, typeArgs, attrs); } - if (la.kind == 27) { - while (!(la.kind == 0 || la.kind == 27)) {SynErr(147); Get();} + if (la.kind == 28) { + while (!(la.kind == 0 || la.kind == 28)) {SynErr(147); Get();} Get(); errors.Warning(t, "the semi-colon that used to terminate an opaque-type declaration has been deprecated; in the new syntax, just leave off the semi-colon"); } @@ -911,19 +931,19 @@ bool IsType(ref IToken pt) { IToken bodyStart = Token.NoToken; IToken bodyEnd = Token.NoToken; - while (!(la.kind == 0 || la.kind == 80)) {SynErr(148); Get();} - Expect(80); - while (la.kind == 45) { + while (!(la.kind == 0 || la.kind == 81)) {SynErr(148); Get();} + Expect(81); + while (la.kind == 46) { Attribute(ref attrs); } NoUSIdent(out id); - if (la.kind == 49 || la.kind == 51) { - if (la.kind == 51) { + if (la.kind == 50 || la.kind == 52) { + if (la.kind == 52) { GenericParameters(typeArgs); } Formals(true, true, ins); - if (la.kind == 81 || la.kind == 82) { - if (la.kind == 81) { + if (la.kind == 82 || la.kind == 83) { + if (la.kind == 82) { Get(); } else { Get(); @@ -931,14 +951,14 @@ bool IsType(ref IToken pt) { } Formals(false, true, outs); } - } else if (la.kind == 58) { + } else if (la.kind == 59) { Get(); signatureEllipsis = t; } else SynErr(149); while (StartOf(5)) { IteratorSpec(reads, mod, decreases, req, ens, yieldReq, yieldEns, ref readsAttrs, ref modAttrs, ref decrAttrs); } - if (la.kind == 45) { + if (la.kind == 46) { BlockStmt(out body, out bodyStart, out bodyEnd); } iter = new IteratorDecl(id, id.val, module, typeArgs, ins, outs, @@ -961,21 +981,21 @@ bool IsType(ref IToken pt) { List members = new List(); IToken bodyStart; - while (!(la.kind == 0 || la.kind == 71)) {SynErr(150); Get();} - Expect(71); - while (la.kind == 45) { + while (!(la.kind == 0 || la.kind == 72)) {SynErr(150); Get();} + Expect(72); + while (la.kind == 46) { Attribute(ref attrs); } NoUSIdent(out id); - if (la.kind == 51) { + if (la.kind == 52) { GenericParameters(typeArgs); } - Expect(45); + Expect(46); bodyStart = t; while (StartOf(2)) { ClassMemberDecl(members, true, false, false); } - Expect(46); + Expect(47); trait = new TraitDecl(id, id.val, module, typeArgs, members, attrs); trait.BodyStartTok = bodyStart; trait.BodyEndTok = t; @@ -989,11 +1009,11 @@ bool IsType(ref IToken pt) { MemberModifiers mmod = new MemberModifiers(); IToken staticToken = null, protectedToken = null; - while (la.kind == 72 || la.kind == 73 || la.kind == 74) { - if (la.kind == 72) { + while (la.kind == 73 || la.kind == 74 || la.kind == 75) { + if (la.kind == 73) { Get(); mmod.IsGhost = true; - } else if (la.kind == 73) { + } else if (la.kind == 74) { Get(); mmod.IsStatic = true; staticToken = t; } else { @@ -1001,7 +1021,7 @@ bool IsType(ref IToken pt) { mmod.IsProtected = true; protectedToken = t; } } - if (la.kind == 77) { + if (la.kind == 78) { if (moduleLevelDecl) { SemErr(la, "fields are not allowed to be declared at the module level; instead, wrap the field in a 'class' declaration"); mmod.IsStatic = false; @@ -1036,14 +1056,14 @@ bool IsType(ref IToken pt) { IToken x; string name; var args = new List(); - Expect(45); + Expect(46); Expect(21); NoUSIdent(out x); name = x.val; if (StartOf(7)) { Expressions(args); } - Expect(46); + Expect(47); attrs = new Attributes(name, args, attrs); } @@ -1061,7 +1081,7 @@ bool IsType(ref IToken pt) { IToken id; ids = new List(); Ident(out id); ids.Add(id); - while (la.kind == 26) { + while (la.kind == 27) { Get(); Ident(out id); ids.Add(id); @@ -1079,13 +1099,13 @@ bool IsType(ref IToken pt) { IToken/*!*/ id; TypeParameter.EqualitySupportValue eqSupport; - Expect(51); + Expect(52); NoUSIdent(out id); eqSupport = TypeParameter.EqualitySupportValue.Unspecified; - if (la.kind == 49) { + if (la.kind == 50) { Get(); - Expect(53); - Expect(50); + Expect(54); + Expect(51); eqSupport = TypeParameter.EqualitySupportValue.Required; } typeArgs.Add(new TypeParameter(id, id.val, eqSupport)); @@ -1093,15 +1113,15 @@ bool IsType(ref IToken pt) { Get(); NoUSIdent(out id); eqSupport = TypeParameter.EqualitySupportValue.Unspecified; - if (la.kind == 49) { + if (la.kind == 50) { Get(); - Expect(53); - Expect(50); + Expect(54); + Expect(51); eqSupport = TypeParameter.EqualitySupportValue.Required; } typeArgs.Add(new TypeParameter(id, id.val, eqSupport)); } - Expect(52); + Expect(53); } void Type(out Type ty) { @@ -1114,11 +1134,11 @@ bool IsType(ref IToken pt) { Attributes attrs = null; IToken/*!*/ id; Type/*!*/ ty; - while (!(la.kind == 0 || la.kind == 77)) {SynErr(152); Get();} - Expect(77); + while (!(la.kind == 0 || la.kind == 78)) {SynErr(152); Get();} + Expect(78); if (mmod.IsStatic) { SemErr(t, "fields cannot be declared 'static'"); } - while (la.kind == 45) { + while (la.kind == 46) { Attribute(ref attrs); } FIdentType(out id, out ty); @@ -1150,48 +1170,48 @@ bool IsType(ref IToken pt) { IToken signatureEllipsis = null; bool missingOpenParen; - if (la.kind == 37) { + if (la.kind == 38) { Get(); - if (la.kind == 83) { + if (la.kind == 84) { Get(); isFunctionMethod = true; } if (mmod.IsGhost) { SemErr(t, "functions cannot be declared 'ghost' (they are ghost by default)"); } - while (la.kind == 45) { + while (la.kind == 46) { Attribute(ref attrs); } NoUSIdent(out id); - if (la.kind == 49 || la.kind == 51) { - if (la.kind == 51) { + if (la.kind == 50 || la.kind == 52) { + if (la.kind == 52) { GenericParameters(typeArgs); } Formals(true, isFunctionMethod, formals); Expect(21); Type(out returnType); - } else if (la.kind == 58) { + } else if (la.kind == 59) { Get(); signatureEllipsis = t; } else SynErr(153); - } else if (la.kind == 38) { + } else if (la.kind == 39) { Get(); isPredicate = true; - if (la.kind == 83) { + if (la.kind == 84) { Get(); isFunctionMethod = true; } if (mmod.IsGhost) { SemErr(t, "predicates cannot be declared 'ghost' (they are ghost by default)"); } - while (la.kind == 45) { + while (la.kind == 46) { Attribute(ref attrs); } NoUSIdent(out id); if (StartOf(8)) { - if (la.kind == 51) { + if (la.kind == 52) { GenericParameters(typeArgs); } missingOpenParen = true; - if (la.kind == 49) { + if (la.kind == 50) { Formals(true, isFunctionMethod, formals); missingOpenParen = false; } @@ -1200,22 +1220,22 @@ bool IsType(ref IToken pt) { Get(); SemErr(t, "predicates do not have an explicitly declared return type; it is always bool"); } - } else if (la.kind == 58) { + } else if (la.kind == 59) { Get(); signatureEllipsis = t; } else SynErr(154); - } else if (la.kind == 39) { + } else if (la.kind == 40) { Get(); - Expect(38); + Expect(39); isIndPredicate = true; if (mmod.IsGhost) { SemErr(t, "inductive predicates cannot be declared 'ghost' (they are ghost by default)"); } - while (la.kind == 45) { + while (la.kind == 46) { Attribute(ref attrs); } NoUSIdent(out id); - if (la.kind == 49 || la.kind == 51) { - if (la.kind == 51) { + if (la.kind == 50 || la.kind == 52) { + if (la.kind == 52) { GenericParameters(typeArgs); } Formals(true, isFunctionMethod, formals); @@ -1223,21 +1243,21 @@ bool IsType(ref IToken pt) { Get(); SemErr(t, "inductive predicates do not have an explicitly declared return type; it is always bool"); } - } else if (la.kind == 58) { + } else if (la.kind == 59) { Get(); signatureEllipsis = t; } else SynErr(155); - } else if (la.kind == 41) { + } else if (la.kind == 42) { Get(); isCoPredicate = true; if (mmod.IsGhost) { SemErr(t, "copredicates cannot be declared 'ghost' (they are ghost by default)"); } - while (la.kind == 45) { + while (la.kind == 46) { Attribute(ref attrs); } NoUSIdent(out id); - if (la.kind == 49 || la.kind == 51) { - if (la.kind == 51) { + if (la.kind == 50 || la.kind == 52) { + if (la.kind == 52) { GenericParameters(typeArgs); } Formals(true, isFunctionMethod, formals); @@ -1245,7 +1265,7 @@ bool IsType(ref IToken pt) { Get(); SemErr(t, "copredicates do not have an explicitly declared return type; it is always bool"); } - } else if (la.kind == 58) { + } else if (la.kind == 59) { Get(); signatureEllipsis = t; } else SynErr(156); @@ -1254,7 +1274,7 @@ bool IsType(ref IToken pt) { while (StartOf(9)) { FunctionSpec(reqs, reads, ens, decreases); } - if (la.kind == 45) { + if (la.kind == 46) { FunctionBody(out body, out bodyStart, out bodyEnd); } if (!isWithinAbstractModule && DafnyOptions.O.DisallowSoundnessCheating && body == null && ens.Count > 0 && !Attributes.Contains(attrs, "axiom") && !Attributes.Contains(attrs, "imported")) { @@ -1310,34 +1330,34 @@ bool IsType(ref IToken pt) { while (!(StartOf(10))) {SynErr(158); Get();} switch (la.kind) { - case 83: { + case 84: { Get(); break; } - case 40: { + case 41: { Get(); isLemma = true; break; } - case 84: { + case 85: { Get(); isCoLemma = true; break; } - case 85: { + case 86: { Get(); isCoLemma = true; errors.Warning(t, "the 'comethod' keyword has been deprecated; it has been renamed to 'colemma'"); break; } - case 39: { + case 40: { Get(); - Expect(40); + Expect(41); isIndLemma = true; break; } - case 86: { + case 87: { Get(); if (allowConstructor) { isConstructor = true; @@ -1371,7 +1391,7 @@ bool IsType(ref IToken pt) { } } - while (la.kind == 45) { + while (la.kind == 46) { Attribute(ref attrs); } if (la.kind == 1) { @@ -1385,24 +1405,24 @@ bool IsType(ref IToken pt) { } } - if (la.kind == 49 || la.kind == 51) { - if (la.kind == 51) { + if (la.kind == 50 || la.kind == 52) { + if (la.kind == 52) { GenericParameters(typeArgs); } Formals(true, !mmod.IsGhost, ins); - if (la.kind == 82) { + if (la.kind == 83) { Get(); if (isConstructor) { SemErr(t, "constructors cannot have out-parameters"); } Formals(false, !mmod.IsGhost, outs); } - } else if (la.kind == 58) { + } else if (la.kind == 59) { Get(); signatureEllipsis = t; } else SynErr(160); while (StartOf(11)) { MethodSpec(req, mod, ens, dec, ref decAttrs, ref modAttrs); } - if (la.kind == 45) { + if (la.kind == 46) { BlockStmt(out body, out bodyStart, out bodyEnd); } if (!isWithinAbstractModule && DafnyOptions.O.DisallowSoundnessCheating && body == null && ens.Count > 0 && !Attributes.Contains(attrs, "axiom") && !Attributes.Contains(attrs, "imported") && !Attributes.Contains(attrs, "decl") && theVerifyThisFile) { @@ -1437,11 +1457,11 @@ bool IsType(ref IToken pt) { IToken/*!*/ id; List formals = new List(); - while (la.kind == 45) { + while (la.kind == 46) { Attribute(ref attrs); } NoUSIdent(out id); - if (la.kind == 49) { + if (la.kind == 50) { FormalsOptionalIds(formals); } ctors.Add(new DatatypeCtor(id, id.val, formals, attrs)); @@ -1449,7 +1469,7 @@ bool IsType(ref IToken pt) { void FormalsOptionalIds(List/*!*/ formals) { Contract.Requires(cce.NonNullElements(formals)); IToken/*!*/ id; Type/*!*/ ty; string/*!*/ name; bool isGhost; - Expect(49); + Expect(50); if (StartOf(12)) { TypeIdentOptional(out id, out name, out ty, out isGhost); formals.Add(new Formal(id, name, ty, true, isGhost)); @@ -1459,7 +1479,7 @@ bool IsType(ref IToken pt) { formals.Add(new Formal(id, name, ty, true, isGhost)); } } - Expect(50); + Expect(51); } void FIdentType(out IToken/*!*/ id, out Type/*!*/ ty) { @@ -1477,8 +1497,8 @@ bool IsType(ref IToken pt) { } void OldSemi() { - if (la.kind == 27) { - while (!(la.kind == 0 || la.kind == 27)) {SynErr(162); Get();} + if (la.kind == 28) { + while (!(la.kind == 0 || la.kind == 28)) {SynErr(162); Get();} Get(); } } @@ -1487,7 +1507,7 @@ bool IsType(ref IToken pt) { Expression e0; IToken endTok; EquivExpression(out e, allowSemi, allowLambda); if (SemiFollowsCall(allowSemi, e)) { - Expect(27); + Expect(28); endTok = t; Expression(out e0, allowSemi, allowLambda); e = new StmtExpr(e.tok, @@ -1501,7 +1521,7 @@ bool IsType(ref IToken pt) { Contract.Ensures(Contract.ValueAtReturn(out id)!=null); Contract.Ensures(Contract.ValueAtReturn(out ty)!=null); isGhost = false; - if (la.kind == 72) { + if (la.kind == 73) { Get(); if (allowGhostKeyword) { isGhost = true; } else { SemErr(t, "formal cannot be declared 'ghost' in this context"); } } @@ -1553,7 +1573,7 @@ bool IsType(ref IToken pt) { Contract.Ensures(Contract.ValueAtReturn(out ty)!=null); Contract.Ensures(Contract.ValueAtReturn(out identName)!=null); string name = null; id = Token.NoToken; ty = new BoolType()/*dummy*/; isGhost = false; - if (la.kind == 72) { + if (la.kind == 73) { Get(); isGhost = true; } @@ -1623,7 +1643,7 @@ bool IsType(ref IToken pt) { case 13: { Get(); tok = t; gt = new List(); - if (la.kind == 51) { + if (la.kind == 52) { GenericInstantiation(gt); } if (gt.Count > 1) { @@ -1636,7 +1656,7 @@ bool IsType(ref IToken pt) { case 14: { Get(); tok = t; gt = new List(); - if (la.kind == 51) { + if (la.kind == 52) { GenericInstantiation(gt); } if (gt.Count > 1) { @@ -1649,7 +1669,7 @@ bool IsType(ref IToken pt) { case 15: { Get(); tok = t; gt = new List(); - if (la.kind == 51) { + if (la.kind == 52) { GenericInstantiation(gt); } if (gt.Count > 1) { @@ -1662,7 +1682,7 @@ bool IsType(ref IToken pt) { case 16: { Get(); tok = t; gt = new List(); - if (la.kind == 51) { + if (la.kind == 52) { GenericInstantiation(gt); } if (gt.Count > 1) { @@ -1680,7 +1700,7 @@ bool IsType(ref IToken pt) { case 17: { Get(); tok = t; gt = new List(); - if (la.kind == 51) { + if (la.kind == 52) { GenericInstantiation(gt); } if (gt.Count == 0) { @@ -1697,7 +1717,7 @@ bool IsType(ref IToken pt) { case 18: { Get(); tok = t; gt = new List(); - if (la.kind == 51) { + if (la.kind == 52) { GenericInstantiation(gt); } if (gt.Count == 0) { @@ -1714,7 +1734,7 @@ bool IsType(ref IToken pt) { case 5: { Get(); tok = t; gt = null; - if (la.kind == 51) { + if (la.kind == 52) { gt = new List(); GenericInstantiation(gt); } @@ -1723,7 +1743,7 @@ bool IsType(ref IToken pt) { break; } - case 49: { + case 50: { Get(); tok = t; tupleArgTypes = new List(); if (StartOf(3)) { @@ -1735,7 +1755,7 @@ bool IsType(ref IToken pt) { tupleArgTypes.Add(ty); } } - Expect(50); + Expect(51); if (tupleArgTypes.Count == 1) { // just return the type 'ty' } else { @@ -1750,11 +1770,11 @@ bool IsType(ref IToken pt) { Expression e; tok = t; NameSegmentForTypeName(out e); tok = t; - while (la.kind == 26) { + while (la.kind == 27) { Get(); Expect(1); tok = t; List typeArgs = null; - if (la.kind == 51) { + if (la.kind == 52) { typeArgs = new List(); GenericInstantiation(typeArgs); } @@ -1765,7 +1785,7 @@ bool IsType(ref IToken pt) { } default: SynErr(164); break; } - if (la.kind == 29) { + if (la.kind == 30) { Type t2; Get(); tok = t; @@ -1783,8 +1803,8 @@ bool IsType(ref IToken pt) { void Formals(bool incoming, bool allowGhostKeyword, List formals) { Contract.Requires(cce.NonNullElements(formals)); IToken id; Type ty; bool isGhost; - Expect(49); - if (la.kind == 1 || la.kind == 72) { + Expect(50); + if (la.kind == 1 || la.kind == 73) { GIdentType(allowGhostKeyword, out id, out ty, out isGhost); formals.Add(new Formal(id, id.val, ty, incoming, isGhost)); while (la.kind == 22) { @@ -1793,7 +1813,7 @@ bool IsType(ref IToken pt) { formals.Add(new Formal(id, id.val, ty, incoming, isGhost)); } } - Expect(50); + Expect(51); } void IteratorSpec(List/*!*/ reads, List/*!*/ mod, List decreases, @@ -1803,7 +1823,7 @@ ref Attributes readsAttrs, ref Attributes modAttrs, ref Attributes decrAttrs) { Expression/*!*/ e; FrameExpression/*!*/ fe; bool isFree = false; bool isYield = false; Attributes ensAttrs = null; while (!(StartOf(13))) {SynErr(165); Get();} - if (la.kind == 43) { + if (la.kind == 44) { Get(); while (IsAttribute()) { Attribute(ref readsAttrs); @@ -1816,7 +1836,7 @@ ref Attributes readsAttrs, ref Attributes modAttrs, ref Attributes decrAttrs) { reads.Add(fe); } OldSemi(); - } else if (la.kind == 42) { + } else if (la.kind == 43) { Get(); while (IsAttribute()) { Attribute(ref modAttrs); @@ -1830,17 +1850,17 @@ ref Attributes readsAttrs, ref Attributes modAttrs, ref Attributes decrAttrs) { } OldSemi(); } else if (StartOf(14)) { - if (la.kind == 87) { + if (la.kind == 88) { Get(); isFree = true; errors.Warning(t, "the 'free' keyword is soon to be deprecated"); } - if (la.kind == 89) { + if (la.kind == 90) { Get(); isYield = true; } - if (la.kind == 44) { + if (la.kind == 45) { Get(); Expression(out e, false, false); OldSemi(); @@ -1850,7 +1870,7 @@ ref Attributes readsAttrs, ref Attributes modAttrs, ref Attributes decrAttrs) { req.Add(new MaybeFreeExpression(e, isFree)); } - } else if (la.kind == 88) { + } else if (la.kind == 89) { Get(); while (IsAttribute()) { Attribute(ref ensAttrs); @@ -1864,7 +1884,7 @@ ref Attributes readsAttrs, ref Attributes modAttrs, ref Attributes decrAttrs) { } } else SynErr(166); - } else if (la.kind == 35) { + } else if (la.kind == 36) { Get(); while (IsAttribute()) { Attribute(ref decrAttrs); @@ -1878,12 +1898,12 @@ ref Attributes readsAttrs, ref Attributes modAttrs, ref Attributes decrAttrs) { Contract.Ensures(Contract.ValueAtReturn(out block) != null); List body = new List(); - Expect(45); + Expect(46); bodyStart = t; while (StartOf(15)) { Stmt(body); } - Expect(46); + Expect(47); bodyEnd = t; block = new BlockStmt(bodyStart, bodyEnd, body); } @@ -1894,7 +1914,7 @@ List/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo Expression/*!*/ e; FrameExpression/*!*/ fe; bool isFree = false; Attributes ensAttrs = null; while (!(StartOf(16))) {SynErr(168); Get();} - if (la.kind == 42) { + if (la.kind == 43) { Get(); while (IsAttribute()) { Attribute(ref modAttrs); @@ -1907,19 +1927,19 @@ List/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo mod.Add(fe); } OldSemi(); - } else if (la.kind == 44 || la.kind == 87 || la.kind == 88) { - if (la.kind == 87) { + } else if (la.kind == 45 || la.kind == 88 || la.kind == 89) { + if (la.kind == 88) { Get(); isFree = true; errors.Warning(t, "the 'free' keyword is soon to be deprecated"); } - if (la.kind == 44) { + if (la.kind == 45) { Get(); Expression(out e, false, false); OldSemi(); req.Add(new MaybeFreeExpression(e, isFree)); - } else if (la.kind == 88) { + } else if (la.kind == 89) { Get(); while (IsAttribute()) { Attribute(ref ensAttrs); @@ -1928,7 +1948,7 @@ List/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo OldSemi(); ens.Add(new MaybeFreeExpression(e, isFree, ensAttrs)); } else SynErr(169); - } else if (la.kind == 35) { + } else if (la.kind == 36) { Get(); while (IsAttribute()) { Attribute(ref decAttrs); @@ -1948,13 +1968,13 @@ List/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo if (StartOf(7)) { Expression(out e, allowSemi, allowLambda); feTok = e.tok; - if (la.kind == 90) { + if (la.kind == 91) { Get(); Ident(out id); fieldName = id.val; feTok = id; } fe = new FrameExpression(feTok, e, fieldName); - } else if (la.kind == 90) { + } else if (la.kind == 91) { Get(); Ident(out id); fieldName = id.val; @@ -1985,7 +2005,7 @@ List/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo void GenericInstantiation(List/*!*/ gt) { Contract.Requires(cce.NonNullElements(gt)); Type/*!*/ ty; - Expect(51); + Expect(52); Type(out ty); gt.Add(ty); while (la.kind == 22) { @@ -1993,7 +2013,7 @@ List/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo Type(out ty); gt.Add(ty); } - Expect(52); + Expect(53); } void NameSegmentForTypeName(out Expression e) { @@ -2001,7 +2021,7 @@ List/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo List typeArgs = null; Ident(out id); - if (la.kind == 51) { + if (la.kind == 52) { typeArgs = new List(); GenericInstantiation(typeArgs); } @@ -2015,12 +2035,12 @@ List/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo Contract.Requires(decreases == null || cce.NonNullElements(decreases)); Expression/*!*/ e; FrameExpression/*!*/ fe; while (!(StartOf(17))) {SynErr(172); Get();} - if (la.kind == 44) { + if (la.kind == 45) { Get(); Expression(out e, false, false); OldSemi(); reqs.Add(e); - } else if (la.kind == 43) { + } else if (la.kind == 44) { Get(); PossiblyWildFrameExpression(out fe, false); reads.Add(fe); @@ -2030,12 +2050,12 @@ List/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo reads.Add(fe); } OldSemi(); - } else if (la.kind == 88) { + } else if (la.kind == 89) { Get(); Expression(out e, false, false); OldSemi(); ens.Add(e); - } else if (la.kind == 35) { + } else if (la.kind == 36) { Get(); if (decreases == null) { SemErr(t, "'decreases' clauses are meaningless for copredicates, so they are not allowed"); @@ -2049,16 +2069,16 @@ List/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo void FunctionBody(out Expression/*!*/ e, out IToken bodyStart, out IToken bodyEnd) { Contract.Ensures(Contract.ValueAtReturn(out e) != null); e = dummyExpr; - Expect(45); + Expect(46); bodyStart = t; Expression(out e, true, true); - Expect(46); + Expect(47); bodyEnd = t; } void PossiblyWildFrameExpression(out FrameExpression fe, bool allowSemi) { Contract.Ensures(Contract.ValueAtReturn(out fe) != null); fe = dummyFrameExpr; - if (la.kind == 56) { + if (la.kind == 57) { Get(); fe = new FrameExpression(t, new WildcardExpr(t), null); } else if (StartOf(18)) { @@ -2069,7 +2089,7 @@ List/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo void PossiblyWildExpression(out Expression e, bool allowLambda) { Contract.Ensures(Contract.ValueAtReturn(out e)!=null); e = dummyExpr; - if (la.kind == 56) { + if (la.kind == 57) { Get(); e = new WildcardExpr(t); } else if (StartOf(7)) { @@ -2093,7 +2113,7 @@ List/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo while (!(StartOf(19))) {SynErr(176); Get();} switch (la.kind) { - case 45: { + case 46: { BlockStmt(out bs, out bodyStart, out bodyEnd); s = bs; break; @@ -2102,7 +2122,7 @@ List/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo AssertStmt(out s); break; } - case 30: { + case 31: { AssumeStmt(out s); break; } @@ -2110,11 +2130,11 @@ List/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo PrintStmt(out s); break; } - case 1: case 2: case 3: case 4: case 8: case 10: case 19: case 20: case 23: case 49: case 131: case 132: case 133: case 134: case 135: case 136: { + case 1: case 2: case 3: case 4: case 8: case 10: case 19: case 20: case 23: case 50: case 131: case 132: case 133: case 134: case 135: case 136: { UpdateStmt(out s); break; } - case 72: case 77: { + case 73: case 78: { VarDeclStatement(out s); break; } @@ -2134,7 +2154,7 @@ List/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo ForallStmt(out s); break; } - case 31: { + case 32: { CalcStmt(out s); break; } @@ -2142,7 +2162,7 @@ List/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo ModifyStmt(out s); break; } - case 91: { + case 92: { Get(); x = t; NoUSIdent(out id); @@ -2151,28 +2171,28 @@ List/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo s.Labels = new LList