diff options
author | Rustan Leino <unknown> | 2015-08-20 11:18:46 -0700 |
---|---|---|
committer | Rustan Leino <unknown> | 2015-08-20 11:18:46 -0700 |
commit | eb146ddaa09123f57b963fd85845c944a73a23cb (patch) | |
tree | 5f91f8ee712839bbd8394f25a516f22052a7a53f /Source/Dafny | |
parent | 69c320b225825eb2adf2ae899f88588a10fd27fe (diff) | |
parent | e5f9a4cbf74f7794ad13b2a5bd831fd54c20629c (diff) |
Merge
Diffstat (limited to 'Source/Dafny')
-rw-r--r-- | Source/Dafny/Cloner.cs | 32 | ||||
-rw-r--r-- | Source/Dafny/Compiler.cs | 5 | ||||
-rw-r--r-- | Source/Dafny/Dafny.atg | 6 | ||||
-rw-r--r-- | Source/Dafny/DafnyAst.cs | 122 | ||||
-rw-r--r-- | Source/Dafny/DafnyMain.cs | 12 | ||||
-rw-r--r-- | Source/Dafny/DafnyOptions.cs | 1 | ||||
-rw-r--r-- | Source/Dafny/DafnyPipeline.csproj | 14 | ||||
-rw-r--r-- | Source/Dafny/Parser.cs | 34 | ||||
-rw-r--r-- | Source/Dafny/Printer.cs | 8 | ||||
-rw-r--r-- | Source/Dafny/RefinementTransformer.cs | 293 | ||||
-rw-r--r-- | Source/Dafny/Reporting.cs | 164 | ||||
-rw-r--r-- | Source/Dafny/Resolver.cs | 1151 | ||||
-rw-r--r-- | Source/Dafny/Rewriter.cs | 183 | ||||
-rw-r--r-- | Source/Dafny/Scanner.cs | 18 | ||||
-rw-r--r-- | Source/Dafny/Translator.cs | 87 | ||||
-rw-r--r-- | Source/Dafny/TriggerGenerator.cs | 1064 | ||||
-rw-r--r-- | Source/Dafny/Triggers/QuantifierSplitter.cs | 95 | ||||
-rw-r--r-- | Source/Dafny/Triggers/QuantifiersCollection.cs | 197 | ||||
-rw-r--r-- | Source/Dafny/Triggers/QuantifiersCollector.cs | 37 | ||||
-rw-r--r-- | Source/Dafny/Triggers/TriggerExtensions.cs | 495 | ||||
-rw-r--r-- | Source/Dafny/Triggers/TriggerUtils.cs | 162 | ||||
-rw-r--r-- | Source/Dafny/Triggers/TriggersCollector.cs | 230 | ||||
-rw-r--r-- | Source/Dafny/Util.cs | 23 |
23 files changed, 2384 insertions, 2049 deletions
diff --git a/Source/Dafny/Cloner.cs b/Source/Dafny/Cloner.cs index e85eeaca..dd2eed69 100644 --- a/Source/Dafny/Cloner.cs +++ b/Source/Dafny/Cloner.cs @@ -706,22 +706,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);
- }
}
/// <summary>
@@ -736,12 +730,12 @@ namespace Microsoft.Dafny {
readonly bool isCoContext;
readonly ISet<Expression> friendlyCalls;
- public FixpointLemmaSpecificationSubstituter(ISet<Expression> friendlyCalls, Expression k, Resolver resolver, bool isCoContext)
- : base(k, resolver)
+ public FixpointLemmaSpecificationSubstituter(ISet<Expression> 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;
}
@@ -761,7 +755,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) {
@@ -772,7 +766,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;
}
}
@@ -807,12 +801,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) {
@@ -837,7 +831,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.Lhs.tok, mse.Member.Name);
+ reporter.Info(MessageSource.Cloner, apply.Lhs.tok, mse.Member.Name);
return c;
}
}
diff --git a/Source/Dafny/Compiler.cs b/Source/Dafny/Compiler.cs index 619638ac..f2cc5d23 100644 --- a/Source/Dafny/Compiler.cs +++ b/Source/Dafny/Compiler.cs @@ -2810,6 +2810,9 @@ namespace Microsoft.Dafny { } else if (expr is QuantifierExpr) {
var e = (QuantifierExpr)expr;
+
+ // Compilation does not check whether a quantifier was split.
+
Contract.Assert(e.Bounds != null); // for non-ghost quantifiers, the resolver would have insisted on finding bounds
var n = e.BoundVars.Count;
Contract.Assert(e.Bounds.Count == n);
@@ -2852,7 +2855,7 @@ namespace Microsoft.Dafny { wr.Write("{0}, ", expr is ForallExpr ? "true" : "false");
wr.Write("@{0} => ", bv.CompileName);
}
- TrExpr(e.LogicalBody());
+ TrExpr(e.LogicalBody(true));
for (int i = 0; i < n; i++) {
wr.Write(")");
}
diff --git a/Source/Dafny/Dafny.atg b/Source/Dafny/Dafny.atg index b945632d..954448af 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.
///</summary>
-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);
}
///<summary>
@@ -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 b998aa47..7328d8dd 100644 --- a/Source/Dafny/DafnyAst.cs +++ b/Source/Dafny/DafnyAst.cs @@ -27,20 +27,22 @@ namespace Microsoft.Dafny { public List<ModuleDefinition> CompileModules; // filled in during resolution.
// Contains the definitions to be used for compilation.
- List<AdditionalInformation> _additionalInformation = new List<AdditionalInformation>();
- public List<AdditionalInformation> AdditionalInformation { get { return _additionalInformation; } }
public readonly ModuleDecl DefaultModule;
public readonly ModuleDefinition DefaultModuleDef;
public readonly BuiltIns BuiltIns;
public readonly List<TranslationTask> 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<ModuleDefinition>();
CompileModules = new List<ModuleDefinition>();
TranslationTasks = new List<TranslationTask>();
@@ -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.
/// </summary>
public enum MatchingValueOption { Empty, Bool, Int, String, Expression }
- public static bool ContainsMatchingValue(Attributes attrs, string nm, ref object value, IEnumerable<MatchingValueOption> allowed, Action<string> errorReporter) {
+ public static bool ContainsMatchingValue(Attributes attrs, string nm, ref object value, IEnumerable<MatchingValueOption> allowed, Action<string> reporter) {
Contract.Requires(nm != null);
Contract.Requires(allowed != null);
- Contract.Requires(errorReporter != null);
+ Contract.Requires(reporter != null);
List<Expression> 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;
}
}
@@ -1550,11 +1552,6 @@ namespace Microsoft.Dafny { set {
Contract.Requires(Parent == null); // set it only once
Contract.Requires(value != null);
- // BUGBUG: The following line is a workaround to tell the verifier that 'value' is not of an Immutable type.
- // A proper solution would be to be able to express that in the program (in a specification or attribute) or
- // to be able to declare 'parent' as [PeerOrImmutable].
- Contract.Requires(value is TopLevelDecl || value is Function || value is Method || value is DatatypeCtor || value is QuantifierExpr);
- //modifies parent;
parent = value;
}
}
@@ -6550,6 +6547,15 @@ namespace Microsoft.Dafny { }
}
+ /// <summary>
+ /// Returns a resolved binary expression
+ /// </summary>
+ public BinaryExpr(Boogie.IToken tok, BinaryExpr.ResolvedOpcode rop, Expression e0, Expression e1)
+ : this(tok, BinaryExpr.ResolvedOp2SyntacticOp(rop), e0, e1) {
+ ResolvedOp = rop;
+ Type = Type.Bool;
+ }
+
public override IEnumerable<Expression> SubExpressions {
get {
yield return E0;
@@ -6844,13 +6850,16 @@ namespace Microsoft.Dafny { }
public abstract class QuantifierExpr : ComprehensionExpr, TypeParameter.ParentType {
+ private readonly int UniqueId;
public List<TypeParameter> TypeArgs;
private static int currentQuantId = -1;
- static int FreshQuantId()
- {
+
+ protected abstract BinaryExpr.ResolvedOpcode SplitResolvedOp { get; }
+
+ static int FreshQuantId() {
return System.Threading.Interlocked.Increment(ref currentQuantId);
}
- private readonly int UniqueId;
+
public string FullName {
get {
return "q$" + UniqueId;
@@ -6877,10 +6886,49 @@ namespace Microsoft.Dafny { this.TypeArgs = tvars;
this.UniqueId = FreshQuantId();
}
- public abstract Expression LogicalBody();
- }
+ private Expression SplitQuantifierToExpression() {
+ Contract.Requires(SplitQuantifier != null && SplitQuantifier.Any());
+ Expression accumulator = SplitQuantifier[0];
+ for (int tid = 1; tid < SplitQuantifier.Count; tid++) {
+ accumulator = new BinaryExpr(Term.tok, SplitResolvedOp, accumulator, SplitQuantifier[tid]);
+ }
+ return accumulator;
+ }
+
+ private List<Expression> _SplitQuantifier;
+ public List<Expression> SplitQuantifier {
+ get {
+ return _SplitQuantifier;
+ }
+ set {
+ _SplitQuantifier = value;
+ SplitQuantifierExpression = SplitQuantifierToExpression();
+ }
+ }
+
+ internal Expression SplitQuantifierExpression { get; private set; }
+
+ public virtual Expression LogicalBody(bool bypassSplitQuantifier = false) {
+ // Don't call this on a quantifier with a Split clause: it's not a real quantifier. The only exception is the Compiler.
+ Contract.Requires(bypassSplitQuantifier || SplitQuantifier == null);
+ throw new cce.UnreachableException(); // This body is just here for the "Requires" clause
+ }
+
+ public override IEnumerable<Expression> SubExpressions {
+ get {
+ if (SplitQuantifier == null) {
+ return base.SubExpressions;
+ } else {
+ return SplitQuantifier;
+ }
+ }
+ }
+ }
+
public class ForallExpr : QuantifierExpr {
+ protected override BinaryExpr.ResolvedOpcode SplitResolvedOp { get { return BinaryExpr.ResolvedOpcode.And; } }
+
public ForallExpr(IToken tok, List<BoundVar> bvars, Expression range, Expression term, Attributes attrs)
: this(tok, new List<TypeParameter>(), bvars, range, term, attrs) {
Contract.Requires(cce.NonNullElements(bvars));
@@ -6893,7 +6941,7 @@ namespace Microsoft.Dafny { Contract.Requires(tok != null);
Contract.Requires(term != null);
}
- public override Expression LogicalBody() {
+ public override Expression LogicalBody(bool bypassSplitQuantifier = false) {
if (Range == null) {
return Term;
}
@@ -6905,6 +6953,8 @@ namespace Microsoft.Dafny { }
public class ExistsExpr : QuantifierExpr {
+ protected override BinaryExpr.ResolvedOpcode SplitResolvedOp { get { return BinaryExpr.ResolvedOpcode.Or; } }
+
public ExistsExpr(IToken tok, List<BoundVar> bvars, Expression range, Expression term, Attributes attrs)
: this(tok, new List<TypeParameter>(), bvars, range, term, attrs) {
Contract.Requires(cce.NonNullElements(bvars));
@@ -6917,7 +6967,7 @@ namespace Microsoft.Dafny { Contract.Requires(tok != null);
Contract.Requires(term != null);
}
- public override Expression LogicalBody() {
+ public override Expression LogicalBody(bool bypassSplitQuantifier = false) {
if (Range == null) {
return Term;
}
@@ -7695,6 +7745,21 @@ namespace Microsoft.Dafny { stmt.SubStatements.Iter(Visit);
VisitOneStmt(stmt);
}
+ public void Visit(IEnumerable<Expression> exprs) {
+ exprs.Iter(Visit);
+ }
+ public void Visit(IEnumerable<Statement> stmts) {
+ stmts.Iter(Visit);
+ }
+ public void Visit(MaybeFreeExpression expr) {
+ Visit(expr.E);
+ }
+ public void Visit(FrameExpression expr) {
+ Visit(expr.E);
+ }
+ public void Visit(IEnumerable<MaybeFreeExpression> exprs) {
+ exprs.Iter(Visit);
+ }
protected virtual void VisitOneExpr(Expression expr) {
Contract.Requires(expr != null);
// by default, do nothing
@@ -7726,6 +7791,21 @@ namespace Microsoft.Dafny { stmt.SubStatements.Iter(s => Visit(s, st));
}
}
+ public void Visit(IEnumerable<Expression> exprs, State st) {
+ exprs.Iter(e => Visit(e, st));
+ }
+ public void Visit(IEnumerable<Statement> stmts, State st) {
+ stmts.Iter(e => Visit(e, st));
+ }
+ public void Visit(MaybeFreeExpression expr, State st) {
+ Visit(expr.E, st);
+ }
+ public void Visit(FrameExpression expr, State st) {
+ Visit(expr.E, st);
+ }
+ public void Visit(IEnumerable<MaybeFreeExpression> exprs, State st) {
+ exprs.Iter(e => Visit(e, st));
+ }
/// <summary>
/// Visit one expression proper. This method is invoked before it is invoked on the
/// sub-parts (sub-expressions and sub-statements). A return value of "true" says to
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 { /// <summary>
/// Returns null on success, or an error string otherwise.
/// </summary>
- public static string ParseCheck(IList<string/*!*/>/*!*/ fileNames, string/*!*/ programName, out Program program)
+ public static string ParseCheck(IList<string/*!*/>/*!*/ 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/DafnyOptions.cs b/Source/Dafny/DafnyOptions.cs index 2eea5717..1986ea6d 100644 --- a/Source/Dafny/DafnyOptions.cs +++ b/Source/Dafny/DafnyOptions.cs @@ -40,6 +40,7 @@ namespace Microsoft.Dafny Bpl.CommandLineOptions.Install(options);
}
+ public bool UnicodeOutput = false;
public bool DisallowSoundnessCheating = false;
public bool Dafnycc = false;
public int Induction = 3;
diff --git a/Source/Dafny/DafnyPipeline.csproj b/Source/Dafny/DafnyPipeline.csproj index a1452b8a..13a1e53e 100644 --- a/Source/Dafny/DafnyPipeline.csproj +++ b/Source/Dafny/DafnyPipeline.csproj @@ -1,4 +1,4 @@ -<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
@@ -8,7 +8,7 @@ <ProjectGuid>{FE44674A-1633-4917-99F4-57635E6FA740}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
- <RootNamespace>DafnyPipeline</RootNamespace>
+ <RootNamespace>Microsoft.Dafny</RootNamespace>
<AssemblyName>DafnyPipeline</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
@@ -143,7 +143,13 @@ </ItemGroup>
<ItemGroup>
<Compile Include="Cloner.cs" />
- <Compile Include="TriggerGenerator.cs" />
+ <Compile Include="Reporting.cs" />
+ <Compile Include="Triggers\QuantifiersCollection.cs" />
+ <Compile Include="Triggers\QuantifierSplitter.cs" />
+ <Compile Include="Triggers\TriggerExtensions.cs" />
+ <Compile Include="Triggers\QuantifiersCollector.cs" />
+ <Compile Include="Triggers\TriggersCollector.cs" />
+ <Compile Include="Triggers\TriggerUtils.cs" />
<Compile Include="Util.cs" />
<Compile Include="Compiler.cs" />
<Compile Include="BigIntegerParser.cs" />
@@ -193,4 +199,4 @@ <Target Name="AfterBuild">
</Target>
-->
-</Project>
\ No newline at end of file +</Project>
diff --git a/Source/Dafny/Parser.cs b/Source/Dafny/Parser.cs index 7e4b2339..7dafb572 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.
///</summary>
-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);
}
///<summary>
@@ -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<Expression/*!*/>/*!*/ 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/Printer.cs b/Source/Dafny/Printer.cs index 6a6a76ba..ce8b54bb 100644 --- a/Source/Dafny/Printer.cs +++ b/Source/Dafny/Printer.cs @@ -1387,7 +1387,7 @@ namespace Microsoft.Dafny { PrintTypeInstantiation(e.OptTypeArguments);
} else if (expr is ExprDotName) {
- var e = (ExprDotName)expr; //CLEMENT: Check the newly added Implicit parameter to make sure that we don't print "_default." DONE in FunctionCall. Where else?
+ var e = (ExprDotName)expr;
// determine if parens are needed
int opBindingStrength = 0x70;
bool parensNeeded = !e.Lhs.IsImplicit && // KRML: I think that this never holds
@@ -1743,6 +1743,12 @@ namespace Microsoft.Dafny { } else if (expr is QuantifierExpr) {
QuantifierExpr e = (QuantifierExpr)expr;
+
+ if (DafnyOptions.O.DafnyPrintResolvedFile != null && e.SplitQuantifier != null) {
+ PrintExpr(e.SplitQuantifierExpression, contextBindingStrength, fragileContext, isRightmost, isFollowedBySemicolon, indent, resolv_count);
+ return;
+ }
+
bool parensNeeded = !isRightmost;
if (parensNeeded) { wr.Write("("); }
wr.Write(e is ForallExpr ? "forall" : "exists");
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<AdditionalInformation> 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<AdditionalInformation> 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<Type>());
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<string, MemberDecl>();
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<string, DatatypeCtor>();
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<Expression> 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<Expression>(), 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<Statement> stmtList) {
Contract.Requires(s != null);
Contract.Requires(stmtList != null);
- var prevErrorCount = reporter.ErrorCount;
+ var prevErrorCount = reporter.Count(ErrorLevel.Error);
CheckIsOkayNewStatement(s, new Stack<string>(), 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<ErrorLevel, List<ErrorMessage>> AllMessages { get; private set; }
+
+ protected ErrorReporter() {
+ ErrorsOnly = false;
+ AllMessages = new Dictionary<ErrorLevel, List<ErrorMessage>>();
+ AllMessages[ErrorLevel.Error] = new List<ErrorMessage>();
+ AllMessages[ErrorLevel.Warning] = new List<ErrorMessage>();
+ AllMessages[ErrorLevel.Info] = new List<ErrorMessage>();
+ }
+
+ 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 cd531cf1..58984b9b 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;
-
- /// <summary>
- /// This method is virtual, because it is overridden in the VSX plug-in for Dafny.
- /// </summary>
- 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;
- /// <summary>
- /// Set whether or not to report warnings. Return the state of the previous behavior.
- /// </summary>
- 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,16 +35,6 @@ namespace Microsoft.Dafny return defaultTempVarIdGenerator.FreshId(prefix);
}
- public Action<AdditionalInformation> AdditionalInformationReporter;
-
- internal void ReportAdditionalInformation(IToken token, string text) {
- Contract.Requires(token != null);
- Contract.Requires(text != null);
- if (AdditionalInformationReporter != null) {
- AdditionalInformationReporter(new AdditionalInformation { Token = token, Text = text, Length = token.val.Length });
- }
- }
-
interface IAmbiguousThing<Thing>
{
/// <summary>
@@ -257,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]
@@ -274,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<ModuleDecl> 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<ModuleDecl> sortedDecls = dependencies.TopologicallySortedComponents();
@@ -309,18 +228,20 @@ namespace Microsoft.Dafny }
var rewriters = new List<IRewriter>();
- 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 QuantifierSplittingRewriter(reporter));
+ rewriters.Add(new TriggerGeneratingRewriter(reporter));
}
- rewriters.Add(new InductionRewriter(this));
+
+ rewriters.Add(new InductionRewriter(reporter));
systemNameInfo = RegisterTopLevelDecls(prog.BuiltIns.SystemModule, false);
prog.CompileModules.Add(prog.BuiltIns.SystemModule);
@@ -364,7 +285,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);
}
@@ -373,19 +294,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;
@@ -393,13 +315,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
@@ -407,18 +329,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));
@@ -436,7 +358,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;
}
@@ -492,7 +414,7 @@ namespace Microsoft.Dafny }
foreach (var module in prog.Modules) {
foreach (var iter in ModuleDefinition.AllIteratorDecls(module.TopLevelDecls)) {
- ReportAdditionalInformation(iter.tok, Printer.IteratorClassToString(iter));
+ reporter.Info(MessageSource.Resolver, iter.tok, Printer.IteratorClassToString(iter));
}
}
// fill in other additional information
@@ -513,19 +435,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));
}
}
}
@@ -564,7 +486,7 @@ namespace Microsoft.Dafny s += "decreases " + Util.Comma(", ", m.Decreases.Expressions, Printer.ExprToString);
// 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);
+ reporter.Info(MessageSource.Resolver, clbl.Tok, s);
}
}
}
@@ -587,7 +509,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) {
@@ -749,11 +671,11 @@ namespace Microsoft.Dafny // resolve
var datatypeDependencies = new Graph<IndDatatypeDecl>();
var codatatypeDependencies = new Graph<CoDatatypeDecl>();
- 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);
}
}
@@ -811,17 +733,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);
}
}
}
@@ -832,9 +754,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);
@@ -858,7 +780,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;
@@ -867,14 +789,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;
@@ -982,7 +904,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;
@@ -1006,7 +928,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
@@ -1016,7 +938,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
@@ -1028,7 +950,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);
@@ -1100,7 +1022,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);
@@ -1108,13 +1030,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);
@@ -1132,7 +1054,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;
}
@@ -1188,9 +1110,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) {
@@ -1214,9 +1136,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);
@@ -1243,7 +1165,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);
@@ -1293,8 +1215,7 @@ namespace Microsoft.Dafny }
- public static bool ResolvePath(ModuleDecl root, List<IToken> Path, out ModuleSignature p, ResolutionErrorReporter reporter) {
- Contract.Requires(reporter != null);
+ public static bool ResolvePath(ModuleDecl root, List<IToken> Path, out ModuleSignature p, ErrorReporter reporter) {
p = root.Signature;
int i = 1;
while (i < Path.Count) {
@@ -1303,7 +1224,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;
}
}
@@ -1358,7 +1279,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
}
@@ -1384,7 +1305,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);
}
}
@@ -1408,14 +1329,14 @@ namespace Microsoft.Dafny new NativeType("long", Int64.MinValue, 0x8000000000000000, "L", false),
};
- public void ResolveTopLevelDecls_Meat(List<TopLevelDecl/*!*/>/*!*/ declarations, Graph<IndDatatypeDecl/*!*/>/*!*/ datatypeDependencies, Graph<CoDatatypeDecl/*!*/>/*!*/ codatatypeDependencies) {
+ public void ResolveTopLevelDecls_Core(List<TopLevelDecl/*!*/>/*!*/ declarations, Graph<IndDatatypeDecl/*!*/>/*!*/ datatypeDependencies, Graph<CoDatatypeDecl/*!*/>/*!*/ 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
@@ -1430,7 +1351,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) {
@@ -1443,10 +1364,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();
@@ -1456,7 +1377,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);
@@ -1475,7 +1396,7 @@ namespace Microsoft.Dafny allTypeParameters.PopMarker();
}
- if (ErrorCount == prevErrorCount) {
+ if (reporter.Count(ErrorLevel.Error) == prevErrorCount) {
foreach (var e in needFiniteBoundsChecks_SetComprehension) {
CheckTypeInference(e.Range); // we need to resolve operators before the call to DiscoverBounds
List<BoundVar> missingBounds;
@@ -1484,7 +1405,7 @@ namespace Microsoft.Dafny e.MissingBounds = missingBounds;
if (e.Finite) {
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);
}
}
}
@@ -1500,7 +1421,7 @@ namespace Microsoft.Dafny 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 = bestBounds;
@@ -1515,7 +1436,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) {
@@ -1537,7 +1458,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;
@@ -1546,16 +1467,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) {
@@ -1607,18 +1528,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 + "\"}");
+ 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;
@@ -1632,7 +1553,7 @@ namespace Microsoft.Dafny foreach (var p in com.Ens) {
var coConclusions = new HashSet<Expression>();
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));
}
@@ -1642,7 +1563,7 @@ namespace Microsoft.Dafny foreach (var p in com.Req) {
var antecedents = new HashSet<Expression>();
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));
}
@@ -1651,7 +1572,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);
@@ -1685,7 +1606,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;
@@ -1720,7 +1641,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");
+ 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.
@@ -1915,11 +1836,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);
@@ -1935,7 +1856,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);
}
}
}
@@ -1953,45 +1874,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<T> : TopDownVisitor<T>
{
- 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)
- {
- Contract.Requires(tok != null);
- resolver.ReportAdditionalInformation(tok, text);
- }
}
#endregion Visitors
@@ -2013,12 +1903,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);
@@ -2026,7 +1916,7 @@ namespace Microsoft.Dafny m.IsTailRecursive = true;
if (tailCall != null) {
// this means there was at least one recursive call
- ReportAdditionalInformation(m.tok, "tail recursive");
+ reporter.Info(MessageSource.Resolver, m.tok, "tail recursive");
}
}
}
@@ -2034,7 +1924,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));
@@ -2043,10 +1933,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);
}
@@ -2106,7 +1996,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);
}
}
@@ -2116,7 +2006,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);
}
}
}
@@ -2124,8 +2014,8 @@ 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,
- (e.Name.Contains("reveal_") || e.Name.Contains("_FULL")) //CLEMENT should this be StartsWith and EndsWith?
+ 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.StartsWith("reveal_") || e.Name.EndsWith("_FULL"))
? ". If you are making an opaque function, make sure that the function can be called."
: ""
);
@@ -2136,7 +2026,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);
}
}
}
@@ -2204,7 +2094,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;
@@ -2260,7 +2150,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;
}
@@ -2308,7 +2198,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;
}
@@ -2354,7 +2244,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;
}
@@ -2366,7 +2256,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;
}
@@ -2381,7 +2271,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;
}
@@ -2418,7 +2308,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<List<Expression>> results = Attributes.FindAllExpressions(attrs, "fuel");
if (results != null) {
@@ -2431,7 +2321,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);
}
}
}
@@ -2443,10 +2333,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;
}
}
@@ -2458,7 +2346,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;
}
}
@@ -2539,6 +2427,7 @@ namespace Microsoft.Dafny return false;
} else if (expr is QuantifierExpr) {
var e = (QuantifierExpr)expr;
+ Contract.Assert(e.SplitQuantifier == null); // No split quantifiers during resolution
var cpos = IsCoContext ? cp : Invert(cp);
if ((cpos == CallingPosition.Positive && e is ExistsExpr) || (cpos == CallingPosition.Negative && e is ForallExpr)) {
if (e.MissingBounds != null && e.MissingBounds.Count != 0) {
@@ -2580,7 +2469,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) {
@@ -2589,10 +2478,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]");
+ resolver.reporter.Info(MessageSource.Resolver, e.tok, e.Function.Name + "#[_k - 1]");
}
}
// do the sub-parts with cp := Neither
@@ -2607,7 +2496,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;
@@ -2648,7 +2537,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);
}
}
}
@@ -2660,7 +2549,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");
}
}
}
@@ -2719,7 +2608,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++;
}
@@ -2774,9 +2663,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:
@@ -2789,12 +2678,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;
@@ -2820,7 +2709,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++;
}
@@ -2832,7 +2721,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++;
}
@@ -2864,21 +2753,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);
@@ -2904,7 +2793,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++;
@@ -2993,10 +2882,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<TypeParameter, Type>(), new Translator());
+ var substituter = new Translator.AlphaConverting_Substituter(cs.Receiver, argsSubstMap, new Dictionary<TypeParameter, Type>(), 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));
+ resolver.reporter.Info(MessageSource.Resolver, s.Tok, "ensures " + Printer.ExprToString(p) + ";");
}
}
}
@@ -3074,26 +2963,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);
}
}
}
@@ -3136,12 +3025,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();
@@ -3152,13 +3041,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;
@@ -3179,7 +3068,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) {
@@ -3199,37 +3088,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;
@@ -3241,7 +3130,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);
}
}
@@ -3249,9 +3138,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;
@@ -3284,12 +3173,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);
@@ -3299,7 +3188,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);
@@ -3406,7 +3295,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;
@@ -3584,12 +3473,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);
}
}
@@ -3609,9 +3498,9 @@ namespace Microsoft.Dafny var r = allTypeParameters.Push(tp.Name, tp);
if (emitErrors) {
if (r == Scope<TypeParameter>.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<TypeParameter>.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);
}
}
}
@@ -3635,10 +3524,10 @@ namespace Microsoft.Dafny case Scope<Thing>.PushResult.Success:
break;
case Scope<Thing>.PushResult.Duplicate:
- Error(tok, "Duplicate {0} name: {1}", kind, name);
+ reporter.Error(MessageSource.Resolver, tok, "Duplicate {0} name: {1}", kind, name);
break;
case Scope<Thing>.PushResult.Shadow:
- Warning(tok, "Shadowed {0} name: {1}", kind, name);
+ reporter.Warning(MessageSource.Resolver, tok, "Shadowed {0} name: {1}", kind, name);
break;
}
}
@@ -3650,7 +3539,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) {
@@ -3678,7 +3567,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) {
@@ -3688,7 +3577,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));
@@ -3697,14 +3586,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();
@@ -3732,7 +3621,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);
@@ -3740,9 +3629,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;
@@ -3757,7 +3646,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
@@ -3798,14 +3687,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));
@@ -3813,7 +3702,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");
}
}
@@ -3821,7 +3710,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);
@@ -3834,7 +3723,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);
}
}
@@ -3882,7 +3771,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
@@ -3904,7 +3793,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();
@@ -3923,7 +3812,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) {
@@ -3936,7 +3825,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);
}
}
@@ -3952,27 +3841,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) {
@@ -4017,7 +3906,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 {
@@ -4032,7 +3921,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 {
@@ -4218,7 +4107,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);
@@ -4239,19 +4128,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) {
@@ -4264,13 +4153,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) {
@@ -4279,7 +4168,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) {
@@ -4289,10 +4178,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) {
@@ -4314,7 +4203,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;
@@ -4329,7 +4218,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);
}
}
@@ -4825,14 +4714,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) {
@@ -4840,17 +4729,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) {
@@ -4859,7 +4748,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");
}
}
}
@@ -4867,11 +4756,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) {
@@ -4879,7 +4768,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.
@@ -4972,24 +4861,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;
@@ -5002,7 +4891,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;
@@ -5021,7 +4910,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} && <boolean expression>\"", 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} && <boolean expression>\"", localVar.Name));
}
}
}
@@ -5031,12 +4920,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");
}
}
}
@@ -5048,14 +4937,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);
@@ -5073,7 +4962,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;
@@ -5091,7 +4980,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
@@ -5116,12 +5005,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);
@@ -5149,13 +5038,13 @@ namespace Microsoft.Dafny bool bodyMustBeSpecOnly = specContextOnly;
var fvs = new HashSet<IVariable>();
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);
@@ -5168,7 +5057,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);
}
}
@@ -5177,9 +5066,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
@@ -5203,7 +5092,7 @@ namespace Microsoft.Dafny loopStack.RemoveAt(loopStack.Count - 1); // pop
} else {
string text = "havoc {" + Util.Comma(", ", fvs, fv => fv.Name) + "};"; // always terminate with a semi-colon
- ReportAdditionalInformation(s.Tok, text);
+ reporter.Info(MessageSource.Resolver, s.Tok, text);
}
} else if (stmt is AlternativeLoopStmt) {
@@ -5213,7 +5102,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);
}
}
@@ -5221,9 +5110,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
@@ -5232,7 +5121,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");
@@ -5241,21 +5130,21 @@ 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)) {
CheckTypeInference(s.Range); // we need to resolve operators before the call to DiscoverBounds
List<BoundVar> missingBounds;
s.Bounds = DiscoverBestBounds_MultipleVars(s.BoundVars, s.Range, true, true, out missingBounds);
@@ -5277,7 +5166,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.
@@ -5301,13 +5190,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));
+ 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");
}
}
}
@@ -5329,7 +5218,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) {
@@ -5337,12 +5226,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));
@@ -5365,7 +5254,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 {
@@ -5373,13 +5262,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);
@@ -5394,10 +5283,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);
}
@@ -5410,7 +5299,7 @@ namespace Microsoft.Dafny var subst = new Dictionary<TypeParameter, Type>();
Dictionary<string, DatatypeCtor> 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
@@ -5440,15 +5329,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
}
@@ -5464,7 +5353,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;
@@ -5500,7 +5389,7 @@ namespace Microsoft.Dafny }
if (dtd != null && memberNamesUsed.Count != dtd.Ctors.Count) {
// We could complain about the syntactic omission of constructors:
- // Error(stmt, "match statement does not cover all constructors");
+ // reporter.Error(MessageSource.Resolver, stmt, "match statement does not cover all constructors");
// but instead we let the verifier do a semantic check.
// So, for now, record the missing constructors:
foreach (var ctr in dtd.Ctors) {
@@ -5535,7 +5424,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<MatchCaseStmt> cases = new List<MatchCaseStmt>();
@@ -5544,7 +5433,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<CasePattern> patterns;
@@ -5701,7 +5590,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 {
@@ -5908,26 +5797,26 @@ namespace Microsoft.Dafny }
if (loopStmt.InferredDecreases) {
string s = "decreases " + Util.Comma(", ", theDecreases, Printer.ExprToString);
- ReportAdditionalInformation(loopStmt.Tok, s);
+ 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<string>(); // 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)");
}
}
}
@@ -5988,10 +5877,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]);
@@ -6001,19 +5890,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);
}
@@ -6023,17 +5912,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<Expression>();
foreach (var ll in update.Lhss) {
@@ -6060,7 +5949,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);
}
@@ -6068,12 +5957,12 @@ 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);
CheckTypeInference(s.Expr); // we need to resolve operators before the call to DiscoverBoundsAux
@@ -6095,12 +5984,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);
@@ -6139,11 +6028,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
@@ -6157,49 +6046,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)) {
@@ -6211,17 +6100,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.
@@ -6248,7 +6137,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");
}
}
@@ -6263,26 +6152,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");
}
}
@@ -6298,9 +6187,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<Statement>.PushResult.Success); // since we just checked for duplicates, we expect the Push to succeed
@@ -6322,13 +6211,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) {
@@ -6350,9 +6239,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) {
@@ -6361,14 +6250,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
@@ -6376,7 +6265,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) {
@@ -6420,7 +6309,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:
@@ -6451,10 +6340,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");
}
}
@@ -6471,9 +6360,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) {
@@ -6485,7 +6374,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;
@@ -6523,7 +6412,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);
@@ -6541,7 +6430,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:
@@ -6574,9 +6463,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");
}
}
@@ -6588,7 +6477,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) {
@@ -6600,7 +6489,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++;
}
@@ -6610,7 +6499,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;
@@ -6633,18 +6522,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) {
@@ -6654,7 +6543,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);
}
}
}
@@ -6664,10 +6553,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);
}
}
}
@@ -6696,7 +6585,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
@@ -6709,20 +6598,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;
@@ -6736,7 +6625,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;
@@ -6762,7 +6651,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;
}
@@ -6986,10 +6875,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
@@ -7039,7 +6928,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
@@ -7051,19 +6940,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);
}
@@ -7075,7 +6964,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) {
@@ -7094,12 +6983,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);
@@ -7107,18 +6996,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) {
@@ -7158,7 +7047,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) {
@@ -7170,7 +7059,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) {
@@ -7184,7 +7073,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) {
@@ -7192,7 +7081,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++;
}
@@ -7209,42 +7098,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;
@@ -7262,7 +7151,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;
@@ -7278,12 +7167,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) {
@@ -7332,7 +7221,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) {
@@ -7347,13 +7236,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);
}
}
}
@@ -7362,7 +7251,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;
@@ -7371,7 +7260,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);
@@ -7382,19 +7271,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();
@@ -7409,7 +7298,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;
@@ -7423,14 +7312,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;
@@ -7447,10 +7336,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;
@@ -7471,7 +7360,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;
@@ -7479,12 +7368,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;
@@ -7496,26 +7385,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) {
@@ -7535,26 +7424,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) {
@@ -7569,27 +7458,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;
@@ -7609,13 +7498,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;
@@ -7632,7 +7521,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) {
@@ -7646,14 +7535,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();
@@ -7666,7 +7555,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)) {
@@ -7685,7 +7574,8 @@ namespace Microsoft.Dafny e.Type = e.Body.Type;
} else if (expr is QuantifierExpr) {
var e = (QuantifierExpr)expr;
- int prevErrorCount = ErrorCount;
+ Contract.Assert(e.SplitQuantifier == null); // No split quantifiers during resolution
+ int prevErrorCount = reporter.Count(ErrorLevel.Error);
bool _val = true;
bool typeQuantifier = Attributes.ContainsBool(e.Attributes, "typeQuantifier", ref _val) && _val;
allTypeParameters.PushMarker();
@@ -7697,19 +7587,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).
@@ -7718,7 +7608,7 @@ namespace Microsoft.Dafny allTypeParameters.PopMarker();
expr.Type = Type.Bool;
- if (prevErrorCount == ErrorCount) {
+ if (prevErrorCount == reporter.Count(ErrorLevel.Error)) {
CheckTypeInference(e.LogicalBody()); // we need to resolve operators before the call to DiscoverBounds
List<BoundVar> missingBounds;
e.Bounds = DiscoverBestBounds_MultipleVars(e.BoundVars, e.LogicalBody(), e is ExistsExpr, true, out missingBounds);
@@ -7729,7 +7619,7 @@ namespace Microsoft.Dafny mb = new List<BoundVar>(); // (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);
}
@@ -7743,7 +7633,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");
@@ -7752,7 +7642,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
@@ -7769,10 +7659,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");
@@ -7781,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
@@ -7790,7 +7680,7 @@ 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)) {
CheckTypeInference(e.Range); // we need to resolve operators before the call to DiscoverBounds
List<BoundVar> missingBounds;
e.Bounds = DiscoverBestBounds_MultipleVars(e.BoundVars, e.Range, true, true, out missingBounds);
@@ -7798,14 +7688,14 @@ namespace Microsoft.Dafny 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");
@@ -7816,7 +7706,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);
}
}
@@ -7832,14 +7722,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");
}
}
}
@@ -7856,12 +7746,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) {
@@ -7891,7 +7781,7 @@ namespace Microsoft.Dafny var subst = new Dictionary<TypeParameter, Type>();
Dictionary<string, DatatypeCtor> 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
@@ -7920,15 +7810,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
}
@@ -7944,7 +7834,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;
@@ -7971,13 +7861,13 @@ 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();
}
if (dtd != null && memberNamesUsed.Count != dtd.Ctors.Count) {
// We could complain about the syntactic omission of constructors:
- // Error(expr, "match expression does not cover all constructors");
+ // reporter.Error(MessageSource.Resolver, expr, "match expression does not cover all constructors");
// but instead we let the verifier do a semantic check.
// So, for now, record the missing constructors:
foreach (var ctr in dtd.Ctors) {
@@ -8009,13 +7899,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<MatchCaseExpr> cases = new List<MatchCaseExpr>();
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<CasePattern> patterns;
@@ -8307,17 +8197,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
@@ -8373,7 +8263,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");
}
}
}
@@ -8396,7 +8286,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;
@@ -8408,7 +8298,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);
@@ -8419,10 +8309,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<Expression>());
ResolveDatatypeValue(opts, rr, pair.Item1.EnclosingDatatype);
@@ -8437,7 +8327,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
@@ -8451,7 +8341,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);
@@ -8459,7 +8349,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) {
@@ -8491,7 +8381,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");
}
}
}
@@ -8515,7 +8405,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)) {
@@ -8525,7 +8415,7 @@ namespace Microsoft.Dafny receiver = new StaticReceiverExpr(expr.tok, (ClassDecl)member.EnclosingClass);
} else {
if (!scope.AllowInstance) {
- Error(expr.tok, "'this' is not allowed in a 'static' context");
+ reporter.Error(MessageSource.Resolver, expr.tok, "'this' is not allowed in a 'static' context");
// nevertheless, set "receiver" to a value so we can continue resolution
}
receiver = new ImplicitThisExpr(expr.tok);
@@ -8537,7 +8427,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
@@ -8551,7 +8441,7 @@ namespace Microsoft.Dafny // ----- 3. static member of the enclosing module
Contract.Assert(member.IsStatic); // moduleInfo.StaticMembers is supposed to contain only static members of the module's implicit class _default
if (ReallyAmbiguousThing(ref 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, ((AmbiguousMemberDecl)member).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, ((AmbiguousMemberDecl)member).ModuleNames());
} else {
var receiver = new StaticReceiverExpr(expr.tok, (ClassDecl)member.EnclosingClass);
r = ResolveExprDotCall(expr.tok, receiver, member, expr.OptTypeArguments, opts.codeContext, allowMethodCall);
@@ -8559,7 +8449,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) {
@@ -8580,7 +8470,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<Type> tpArgs = new List<Type>();
@@ -8632,7 +8522,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");
}
}
}
@@ -8655,10 +8545,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<Expression>());
ResolveExpression(rr, opts);
@@ -8673,7 +8563,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
@@ -8686,13 +8576,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) {
@@ -8711,7 +8601,7 @@ namespace Microsoft.Dafny Dictionary<string, MemberDecl> 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);
@@ -8724,7 +8614,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<Expression>());
ResolveDatatypeValue(opts, rr, ctor.EnclosingDatatype);
@@ -8737,7 +8627,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
@@ -8797,7 +8687,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");
}
}
}
@@ -8816,7 +8706,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.
@@ -8827,14 +8717,14 @@ namespace Microsoft.Dafny // ----- 1. static member of the specified module
Contract.Assert(member.IsStatic); // moduleInfo.StaticMembers is supposed to contain only static members of the module's implicit class _default
if (ReallyAmbiguousThing(ref 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, ((AmbiguousMemberDecl)member).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, ((AmbiguousMemberDecl)member).ModuleNames());
} else {
var receiver = new StaticReceiverExpr(expr.tok, (ClassDecl)member.EnclosingClass);
r = ResolveExprDotCall(expr.tok, receiver, member, expr.OptTypeArguments, opts.codeContext, allowMethodCall);
}
#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) {
@@ -8850,7 +8740,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);
}
}
@@ -8887,14 +8777,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<Type>();
if (udt != null && udt.ResolvedClass != null) {
@@ -8912,11 +8802,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<Type>();
if (udt != null && udt.ResolvedClass != null) {
@@ -8961,7 +8851,7 @@ namespace Microsoft.Dafny Contract.Requires(opts != null);
Contract.Ensures(Contract.Result<MethodCallInformation>() == 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
@@ -8979,18 +8869,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) :
@@ -9002,7 +8892,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 {
@@ -9012,10 +8902,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 {
@@ -9023,14 +8913,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)
@@ -9055,7 +8945,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);
@@ -9097,12 +8987,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;
@@ -9113,7 +9003,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++;
@@ -9157,14 +9047,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;
}
@@ -9172,7 +9062,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
@@ -9197,13 +9087,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;
}
@@ -9218,7 +9108,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;
@@ -9229,7 +9119,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;
@@ -9257,9 +9147,10 @@ namespace Microsoft.Dafny return;
} else if (expr is QuantifierExpr) {
var e = (QuantifierExpr)expr;
+ Contract.Assert(e.SplitQuantifier == null); // No split quantifiers during resolution
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;
}
@@ -9267,7 +9158,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;
}
@@ -9304,9 +9195,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;
@@ -9314,10 +9205,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) {
@@ -9329,9 +9220,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
@@ -9349,7 +9240,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);
@@ -9403,7 +9294,7 @@ namespace Microsoft.Dafny /// </summary>
public static List<ComprehensionExpr.BoundedPool> DiscoverBestBounds_MultipleVars<VT>(List<VT> bvars, Expression expr, bool polarity, bool onlyFiniteBounds, out List<VT> missingBounds) where VT : IVariable {
foreach (var bv in bvars) {
- var c = TypeConstraint(bv, bv.Type);
+ var c = TypeConstraint(bv, bv.Type, null);
expr = polarity ? Expression.CreateAnd(c, expr) : Expression.CreateImplies(c, expr);
}
var all = DiscoverAllBounds_Aux_MultipleVars(bvars, expr, polarity);
@@ -9418,7 +9309,7 @@ namespace Microsoft.Dafny }
public static List<ComprehensionExpr.BoundedPool> DiscoverAllBounds_SingleVar<VT>(VT v, Expression expr) where VT : IVariable {
- expr = Expression.CreateAnd(TypeConstraint(v, v.Type), expr);
+ expr = Expression.CreateAnd(TypeConstraint(v, v.Type, null), expr);
return DiscoverAllBounds_Aux_SingleVar(new List<VT> { v }, 0, expr, true);
}
@@ -9532,15 +9423,15 @@ namespace Microsoft.Dafny return bounds;
}
- 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;
}
@@ -9806,6 +9697,8 @@ namespace Microsoft.Dafny } else if (expr is QuantifierExpr) {
var e = (QuantifierExpr)expr;
+ Contract.Assert(e.SplitQuantifier == null); // No split quantifiers during resolution
+
var s = FreeVariables(e.LogicalBody());
foreach (var bv in e.BoundVars) {
s.Remove(bv);
@@ -9884,7 +9777,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
@@ -9892,13 +9785,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);
}
}
}
@@ -9906,7 +9799,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) {
@@ -9914,7 +9807,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) {
@@ -10106,7 +9999,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)) ||
@@ -10167,7 +10060,9 @@ namespace Microsoft.Dafny } else if (expr is NamedExpr) {
return moduleInfo.IsGhost ? false : UsesSpecFeatures(((NamedExpr)expr).Body);
} else if (expr is ComprehensionExpr) {
- if (expr is QuantifierExpr && ((QuantifierExpr)expr).Bounds.Contains(null)) {
+ var q = expr as QuantifierExpr;
+ Contract.Assert(q == null || q.SplitQuantifier == null); // No split quantifiers during resolution
+ if (q != null && q.Bounds.Contains(null)) {
return true; // the quantifier cannot be compiled if the resolver found no bounds
}
return Contract.Exists(expr.SubExpressions, se => UsesSpecFeatures(se));
diff --git a/Source/Dafny/Rewriter.cs b/Source/Dafny/Rewriter.cs index f107a819..83f49a12 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,65 @@ namespace Microsoft.Dafny }
}
- public class TriggersRewriter : IRewriter {
- Resolver Resolver;
+ public class TriggerGeneratingRewriter : IRewriter {
+ internal TriggerGeneratingRewriter(ErrorReporter reporter) : base(reporter) {
+ Contract.Requires(reporter != null);
+ }
- internal TriggersRewriter(Resolver resolver) {
- Contract.Requires(resolver != null);
- this.Resolver = resolver;
+ internal override void PostCyclicityResolve(ModuleDefinition m) {
+ var finder = new Triggers.QuantifierCollector(reporter);
+
+ foreach (var decl in ModuleDefinition.AllCallables(m.TopLevelDecls)) {
+ if (decl is Function) {
+ var function = (Function)decl;
+ finder.Visit(function.Ens, null);
+ finder.Visit(function.Req, null);
+ if (function.Body != null) {
+ finder.Visit(function.Body, null);
+ }
+ } else if (decl is Method) {
+ var method = (Method)decl;
+ finder.Visit(method.Ens, null);
+ finder.Visit(method.Req, null);
+ if (method.Body != null) {
+ finder.Visit(method.Body, null);
+ }
+ }
+ }
+
+ var triggersCollector = new Triggers.TriggersCollector();
+ foreach (var quantifierCollection in finder.quantifierCollections) {
+ quantifierCollection.ComputeTriggers(triggersCollector);
+ quantifierCollection.CommitTriggers();
+ }
}
+ }
- public void PreResolve(ModuleDefinition m) { }
+ internal class QuantifierSplittingRewriter : IRewriter {
+ internal QuantifierSplittingRewriter(ErrorReporter reporter) : base(reporter) {
+ Contract.Requires(reporter != null);
+ }
- public void PostResolve(ModuleDefinition m) {
+ internal override void PostResolve(ModuleDefinition m) {
+ var splitter = new Triggers.QuantifierSplitter();
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);
+ splitter.Visit(function.Ens);
+ splitter.Visit(function.Req);
+ if (function.Body != null) {
+ splitter.Visit(function.Body);
+ }
} else if (decl is Method) {
var method = (Method)decl;
- TriggerGenerator.AddTriggers(method.Ens, Resolver);
- TriggerGenerator.AddTriggers(method.Req, Resolver);
- TriggerGenerator.AddTriggers(method.Body, Resolver);
+ splitter.Visit(method.Ens);
+ splitter.Visit(method.Req);
+ if (method.Body != null) {
+ splitter.Visit(method.Body);
+ }
}
}
}
-
- public void PostCyclicityResolve(ModuleDefinition m) { }
}
/// <summary>
@@ -106,7 +139,12 @@ namespace Microsoft.Dafny /// </summary>
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 +200,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 +209,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 +451,20 @@ namespace Microsoft.Dafny /// specifically asks to see it via the reveal_foo() lemma
/// </summary>
public class OpaqueFunctionRewriter : IRewriter {
- readonly ResolutionErrorReporter reporter;
protected Dictionary<Function, Function> fullVersion; // Given an opaque function, retrieve the full
protected Dictionary<Function, Function> original; // Given a full version of an opaque function, find the original opaque version
protected Dictionary<Lemma, Function> 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<Function, Function>();
original = new Dictionary<Function, Function>();
revealOriginal = new Dictionary<Lemma, Function>();
}
- 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 +472,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 +497,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 +542,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 +756,16 @@ namespace Microsoft.Dafny /// </summary>
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 +838,6 @@ namespace Microsoft.Dafny }
}
- public void PostCyclicityResolve(ModuleDefinition m) {
- }
-
Expression subVars(List<Formal> formals, List<Expression> values, Expression e, Expression f_this) {
Contract.Assert(formals != null);
Contract.Assert(values != null);
@@ -839,7 +868,7 @@ namespace Microsoft.Dafny }
if (!tip.Equals("")) {
- resolver.ReportAdditionalInformation(f.tok, tip);
+ 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 +895,7 @@ namespace Microsoft.Dafny }
if (!tip.Equals("")) {
- resolver.ReportAdditionalInformation(method.tok, tip);
+ 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 +1090,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) + ") &&");
+ reporter.Info(MessageSource.Rewriter, e.tok, "autoreq added (" + Printer.ExtendedExprToString(allReqsSatisfied) + ") &&");
}
} else if (expr is SetComprehension) {
var e = (SetComprehension)expr;
@@ -1108,7 +1137,12 @@ namespace Microsoft.Dafny /// </summary>
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 +1170,6 @@ namespace Microsoft.Dafny }
}
}
-
- public void PostResolve(ModuleDefinition m)
- {
- // Nothing to do here
- }
-
- public void PostCyclicityResolve(ModuleDefinition m) {
- // Nothing to do here
- }
-
}
@@ -1269,18 +1293,12 @@ namespace Microsoft.Dafny // ===========================================================================================
- public class InductionRewriter : IRewriter
- {
- Resolver Resolver;
- internal InductionRewriter(Resolver resolver) {
- Contract.Requires(resolver != null);
- this.Resolver = resolver;
- }
- public void PreResolve(ModuleDefinition m) {
- }
- public void PostResolve(ModuleDefinition m) {
+ public class InductionRewriter : IRewriter {
+ internal InductionRewriter(ErrorReporter reporter) : base(reporter) {
+ Contract.Requires(reporter != null);
}
- public void PostCyclicityResolve(ModuleDefinition m) {
+
+ internal override void PostCyclicityResolve(ModuleDefinition m) {
if (DafnyOptions.O.Induction == 0) {
// Don't bother inferring :induction attributes. This will also have the effect of not warning about malformed :induction attributes
} else {
@@ -1316,6 +1334,7 @@ namespace Microsoft.Dafny }
}
}
+
void ProcessMethodExpressions(Method method) {
Contract.Requires(method != null);
var visitor = new Induction_Visitor(this);
@@ -1325,6 +1344,7 @@ namespace Microsoft.Dafny visitor.Visit(method.Body);
}
}
+
void ProcessFunctionExpressions(Function function) {
Contract.Requires(function != null);
var visitor = new Induction_Visitor(this);
@@ -1334,6 +1354,7 @@ namespace Microsoft.Dafny visitor.Visit(function.Body);
}
}
+
void ComputeLemmaInduction(Method method) {
Contract.Requires(method != null);
if (method.Body != null && method.IsGhost && method.Mod.Expressions.Count == 0 && method.Outs.Count == 0 && !(method is FixpointLemma)) {
@@ -1343,6 +1364,7 @@ namespace Microsoft.Dafny ComputeInductionVariables(method.tok, method.Ins, specs, method, ref method.Attributes);
}
}
+
void ComputeInductionVariables<VarType>(IToken tok, List<VarType> boundVars, List<Expression> searchExprs, Method lemma, ref Attributes attributes) where VarType : class, IVariable {
Contract.Requires(tok != null);
Contract.Requires(boundVars != null);
@@ -1383,12 +1405,12 @@ namespace Microsoft.Dafny continue;
}
if (0 <= boundVars.FindIndex(v => v == ie.Var)) {
- Resolver.Warning(arg.tok, "{0}s given as :induction arguments must be given in the same order as in the {1}; ignoring attribute",
+ reporter.Warning(MessageSource.Rewriter, arg.tok, "{0}s given as :induction arguments must be given in the same order as in the {1}; ignoring attribute",
lemma != null ? "lemma parameter" : "bound variable", lemma != null ? "lemma" : "quantifier");
return;
}
}
- Resolver.Warning(arg.tok, "invalid :induction attribute argument; expected {0}{1}; ignoring attribute",
+ reporter.Warning(MessageSource.Rewriter, arg.tok, "invalid :induction attribute argument; expected {0}{1}; ignoring attribute",
i == 0 ? "'false' or 'true' or " : "",
lemma != null ? "lemma parameter" : "bound variable");
return;
@@ -1413,7 +1435,7 @@ namespace Microsoft.Dafny if (lemma is PrefixLemma) {
s = lemma.Name + " " + s;
}
- Resolver.ReportAdditionalInformation(tok, s);
+ reporter.Info(MessageSource.Rewriter, tok, s);
}
}
class Induction_Visitor : BottomUpVisitor
@@ -1425,7 +1447,7 @@ namespace Microsoft.Dafny }
protected override void VisitOneExpr(Expression expr) {
var q = expr as QuantifierExpr;
- if (q != null) {
+ if (q != null && q.SplitQuantifier == null) {
IndRewriter.ComputeInductionVariables(q.tok, q.BoundVars, new List<Expression>() { q.LogicalBody() }, null, ref q.Attributes);
}
}
@@ -1611,3 +1633,4 @@ namespace Microsoft.Dafny }
}
+
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 2ae03412..8cc32e18 100644 --- a/Source/Dafny/Translator.cs +++ b/Source/Dafny/Translator.cs @@ -93,9 +93,11 @@ namespace Microsoft.Dafny { }
public class Translator {
+ ErrorReporter reporter;
[NotDelayed]
- public Translator() {
+ public Translator(ErrorReporter reporter) {
+ this.reporter = reporter;
InsertChecksums = 0 < CommandLineOptions.Clo.VerifySnapshots;
Bpl.Program boogieProgram = ReadPrelude();
if (boogieProgram != null) {
@@ -3583,7 +3585,7 @@ namespace Microsoft.Dafny { Contract.Requires(tok != null);
Contract.Ensures(Contract.Result<Bpl.Cmd>() != 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<object>() { description }, null);
return new Bpl.AssumeCmd(tok, Bpl.Expr.True, kv);
}
@@ -4435,6 +4437,11 @@ namespace Microsoft.Dafny { var e = (ComprehensionExpr)expr;
var canCall = CanCallAssumption(e.Term, etran);
var q = e as QuantifierExpr;
+
+ if (q != null && q.SplitQuantifier != null) {
+ return CanCallAssumption(q.SplitQuantifierExpression, etran);
+ }
+
var tyvars = MkTyParamBinders(q != null ? q.TypeArgs : new List<TypeParameter>());
if (e.Range != null) {
canCall = BplAnd(CanCallAssumption(e.Range, etran), BplImp(etran.TrExpr(e.Range), canCall));
@@ -4728,6 +4735,12 @@ namespace Microsoft.Dafny { // If the quantifier is universal, then continue as:
// assume (\forall x :: body(x));
// Create local variables corresponding to the type arguments:
+
+ if (e.SplitQuantifier != null) {
+ CheckWellformedAndAssume(e.SplitQuantifierExpression, options, locals, builder, etran);
+ return;
+ }
+
var typeArgumentCopies = Map(e.TypeArgs, tp => e.Refresh(tp, CurrentIdGenerator));
var typeMap = Util.Dict(e.TypeArgs, Map(typeArgumentCopies, tp => (Type)new UserDefinedType(tp)));
var newLocals = Map(typeArgumentCopies, tp => new Bpl.LocalVariable(tp.tok, new TypedIdent(tp.tok, nameTypeParam(tp), predef.Ty)));
@@ -5263,6 +5276,11 @@ namespace Microsoft.Dafny { var q = e as QuantifierExpr;
var lam = e as LambdaExpr;
+ if (q != null && q.SplitQuantifier != null) {
+ CheckWellformedWithResult(q.SplitQuantifierExpression, options, result, resultType, locals, builder, etran);
+ return;
+ }
+
var typeMap = new Dictionary<TypeParameter, Type>();
var copies = new List<TypeParameter>();
if (q != null) {
@@ -6407,7 +6425,7 @@ namespace Microsoft.Dafny { }
// Make the call
- builder.Add(new Bpl.CallCmd(method.tok, method.FullSanitizedName, ins, outs));
+ builder.Add(Call(method.tok, method.FullSanitizedName, ins, outs));
for (int i = 0; i < m.Outs.Count; i++) {
var bLhs = m.Outs[i];
@@ -6438,6 +6456,18 @@ namespace Microsoft.Dafny { Reset();
}
+ private static CallCmd Call(IToken tok, string methodName, List<Expr> ins, List<Bpl.IdentifierExpr> outs) {
+ Contract.Requires(tok != null);
+ Contract.Requires(methodName != null);
+ Contract.Requires(ins != null);
+ Contract.Requires(outs != null);
+
+ CallCmd call;
+ call = new CallCmd(tok, methodName, ins, outs);
+ // CLEMENT enable this: call.ErrorData = "possible violation of function precondition";
+ return call;
+ }
+
private static QKeyValue ErrorMessageAttribute(IToken t, string error) {
var l = new List<object>(1);
l.Add(error);
@@ -7929,13 +7959,6 @@ namespace Microsoft.Dafny { }
}
- //CLEMENT: Remove
- //public static Expr PrintAndDie(Expr expr, [System.Runtime.CompilerServices.CallerMemberName] string caller = "", [System.Runtime.CompilerServices.CallerLineNumber] int linum = 0) {
- // Console.Error.WriteLine("In {0} at line {1}: {2}", caller, linum, expr.ToString());
- // Environment.Exit(1);
- // return expr;
- //}
-
/// <summary>
/// Generate:
/// assume (forall x,y :: Range(x,y)[$Heap:=oldHeap] ==>
@@ -8806,7 +8829,7 @@ namespace Microsoft.Dafny { builder.Add(new CommentCmd("ProcessCallStmt: Make the call"));
// Make the call
- Bpl.CallCmd call = new Bpl.CallCmd(tok, MethodName(callee, kind), ins, outs);
+ Bpl.CallCmd call = Call(tok, MethodName(callee, kind), ins, outs);
if (module != currentModule && RefinementToken.IsInherited(tok, currentModule) && (codeContext == null || !codeContext.MustReverify)) {
// The call statement is inherited, so the refined module already checked that the precondition holds. Note,
// preconditions are not allowed to be strengthened, except if they use a predicate whose body has been strengthened.
@@ -10476,7 +10499,6 @@ namespace Microsoft.Dafny { 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; // CLEMENT Where is this used?
public readonly bool stripLits = false;
[ContractInvariantMethod]
void ObjectInvariant()
@@ -11164,7 +11186,7 @@ namespace Microsoft.Dafny { bool liftLit = lit0 != null && lit1 != null;
// NOTE(namin): We usually avoid keeping literals, because their presence might mess up triggers that do not expect them.
// Still for equality-related operations, it's useful to keep them instead of lifting them, so that they can be propagated.
- bool keepLits = false; // CLEMENT: I don't really understand this
+ bool keepLits = false;
if (lit0 != null) {
e0 = lit0;
}
@@ -11983,7 +12005,7 @@ namespace Microsoft.Dafny { parms.Add(s);
} else {
var e = TrExpr(arg);
- e = translator.RemoveLit(e); // CLEMENT: Why?
+ e = translator.RemoveLit(e);
parms.Add(e);
}
}
@@ -12863,6 +12885,8 @@ namespace Microsoft.Dafny { // that needed to be proved about the function was proved already in the previous module, even without the body definition).
} else if (!FunctionBodyIsAvailable(f, currentModule)) {
// Don't inline opaque functions or foreign protected functions
+ } else if (Attributes.Contains(f.Attributes, "no_inline")) {
+ // User manually prevented inlining
} else if (CanSafelyInline(fexp, f)) {
// inline this body
var body = GetSubstitutedBody(fexp, f, false);
@@ -12927,15 +12951,16 @@ 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.");
+ // TODO 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.");
}
}
+ } else if (expr is QuantifierExpr && ((QuantifierExpr)expr).SplitQuantifier != null) {
+ return TrSplitExpr(((QuantifierExpr)expr).SplitQuantifierExpression, splits, position, heightLimit, apply_induction, etran);
} else if (((position && expr is ForallExpr) || (!position && expr is ExistsExpr))
- /* NB: only for type arg less quantifiers for now: */
- && ((QuantifierExpr)expr).TypeArgs.Count == 0) {
+ /* NB: only for type arg less quantifiers for now: */
+ && ((QuantifierExpr)expr).TypeArgs.Count == 0) {
var e = (QuantifierExpr)expr;
var inductionVariables = ApplyInduction(e.BoundVars, e.Attributes);
if (apply_induction && inductionVariables.Count != 0) {
@@ -13069,13 +13094,16 @@ namespace Microsoft.Dafny { visitor.Visit(f.Body);
foreach (var expr in f.Ens) { visitor.Visit(expr); }
foreach (var expr in f.Req) { visitor.Visit(expr); }
- // CLEMENT: Anything else?
+ foreach (var expr in f.Reads) { visitor.Visit(expr); }
+ foreach (var expr in f.Decreases.Expressions) { visitor.Visit(expr); }
return f.Formals.Zip(fexp.Args).All(formal_concrete => CanSafelySubstitute(visitor.TriggerVariables, formal_concrete.Item1, formal_concrete.Item2));
}
+ Triggers.TriggersCollector triggersCollector = new Triggers.TriggersCollector();
+
private bool CanSafelySubstitute(ISet<IVariable> protectedVariables, IVariable variable, Expression substitution) {
- return !(protectedVariables.Contains(variable) && TriggerGenerator.IsTriggerKiller(substitution));
+ return !(protectedVariables.Contains(variable) && triggersCollector.IsTriggerKiller(substitution));
}
private class VariablesCollector: BottomUpVisitor {
@@ -13103,8 +13131,11 @@ namespace Microsoft.Dafny { protected override void VisitOneExpr(Expression expr) {
if (expr is QuantifierExpr) {
- foreach (var trigger in (expr as QuantifierExpr).Attributes.AsEnumerable().Where(a => a.Name == "trigger").SelectMany(a => a.Args)) {
- collector.Visit(trigger);
+ var e = (QuantifierExpr)expr;
+ if (e.SplitQuantifier == null) {
+ foreach (var trigger in (expr as QuantifierExpr).Attributes.AsEnumerable().Where(a => a.Name == "trigger").SelectMany(a => a.Args)) {
+ collector.Visit(trigger);
+ }
}
}
}
@@ -13643,6 +13674,12 @@ namespace Microsoft.Dafny { var e = (ComprehensionExpr)expr;
// For quantifiers and setComprehesion we want to make sure that we don't introduce name clashes with
// the enclosing scopes.
+
+ var q = e as QuantifierExpr;
+ if (q != null && q.SplitQuantifier != null) {
+ return Substitute(q.SplitQuantifierExpression);
+ }
+
var newBoundVars = CreateBoundVarSubstitutions(e.BoundVars, expr is ForallExpr || expr is ExistsExpr || expr is SetComprehension);
Expression newRange = e.Range == null ? null : Substitute(e.Range);
Expression newTerm = Substitute(e.Term);
@@ -14117,12 +14154,12 @@ namespace Microsoft.Dafny { // Bpl-making-utilities
- static Bpl.Expr BplForall(IEnumerable<Bpl.Variable> args_in, Bpl.Expr body) { // NO_TRIGGER
+ static Bpl.Expr BplForall(IEnumerable<Bpl.Variable> args_in, Bpl.Expr body) {
Contract.Requires(args_in != null);
Contract.Requires(body != null);
Contract.Ensures(Contract.Result<Bpl.Expr>() != null);
var args = new List<Bpl.Variable>(args_in);
- if (args.Count == 0) { // CLEMENT don't add quantifiers if the body is trivial
+ if (args.Count == 0) {
return body;
} else {
return new Bpl.ForallExpr(body.tok, args, body); // NO_TRIGGER
diff --git a/Source/Dafny/TriggerGenerator.cs b/Source/Dafny/TriggerGenerator.cs deleted file mode 100644 index 067336a3..00000000 --- a/Source/Dafny/TriggerGenerator.cs +++ /dev/null @@ -1,1064 +0,0 @@ -// #define DEBUG_AUTO_TRIGGERS
-#define THROW_UNSUPPORTED_COMPARISONS
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using Microsoft.Boogie;
-using System.Diagnostics.Contracts;
-using System.Text;
-using System.Diagnostics;
-
-//FIXME Generated triggers should be _triggers
-//FIXME: When scoring, do not consider old(x) to be higher than x.
-
-/* High level note: There are really two processes going on here. One is finding quantifiers;
- * the other is walking the subtree corresponding to each quantifier, and finding trigger candidates.
- * These two processes are interleaved, because we can look for trigger candidates as we look for
- * quantifiers. Since the visitor starts from the bottom of the tree, the recursive annotation
- * procedure never causes deep recursion; every call it makes hits the cache that has been built
- * during the visiting of lower level nodes.
- *
- * Note also that it wouldn't be enough to just use the recursive procedure: it doesn't visit
- * statements, for example.
- */
-
-namespace Microsoft.Dafny {
- class TriggerCandidate {
- internal Expression Expr;
- internal ISet<IVariable> Variables;
- internal List<ExprExtensions.TriggerMatch> MatchesInQuantifierBody;
-
- public override string ToString() {
- return Printer.ExprToString(Expr);
- }
- }
-
- class MultiTriggerCandidate {
- internal List<TriggerCandidate> Candidates;
- internal List<string> Tags;
- internal double Score;
-
- private List<ExprExtensions.TriggerMatch> potentialMatchingLoops;
- internal List<ExprExtensions.TriggerMatch> PotentialMatchingLoops {
- get {
- if (potentialMatchingLoops == null) {
- //FIXME could be optimized by looking at the bindings instead of doing full equality
- var candidates = Candidates.Deduplicate((x, y) => ExprExtensions.ExpressionEq(x.Expr, y.Expr));
- potentialMatchingLoops = candidates.SelectMany(candidate => candidate.MatchesInQuantifierBody)
- .Deduplicate((x, y) => ExprExtensions.ExpressionEq(x.Expr, y.Expr)).Where(tm => tm.CouldCauseLoops(candidates)).ToList();
- }
-
- return potentialMatchingLoops;
- }
- }
-
- internal MultiTriggerCandidate(List<TriggerCandidate> candidates) {
- Candidates = candidates;
- Tags = new List<string>();
- }
-
- internal bool MentionsAll(List<BoundVar> vars) {
- var candidates = Candidates;
- return vars.All(x => candidates.Any(candidate => candidate.Variables.Contains(x))); //TODO Perfs?
- }
-
- public override string ToString() {
- return String.Format("[{0:G2}] {1}", Score, String.Join(", ", Candidates));
- }
-
- public String AsDafnyAttributeString(bool wrap = true, bool includeTags = false) {
- var repr = Candidates.MapConcat(t => Printer.ExprToString(t.Expr), ", ");
- if (wrap) {
- repr = "{:trigger " + repr + "}";
- }
- if (includeTags && Tags != null) {
- repr += " (" + String.Join("; ", Tags) + ")";
- }
- return repr;
- }
- }
-
-
- class TriggerAnnotation {
- internal bool IsTriggerKiller;
- internal ISet<IVariable> Variables;
- internal readonly List<TriggerCandidate> PrivateCandidates;
- internal readonly List<TriggerCandidate> ExportedCandidates;
-
- internal TriggerAnnotation(bool IsTriggerKiller, IEnumerable<IVariable> Variables,
- IEnumerable<TriggerCandidate> AllCandidates, IEnumerable<TriggerCandidate> PrivateCandidates = null) {
- this.IsTriggerKiller = IsTriggerKiller;
- this.Variables = new HashSet<IVariable>(Variables);
-
- this.PrivateCandidates = new List<TriggerCandidate>(PrivateCandidates == null ? Enumerable.Empty<TriggerCandidate>() : PrivateCandidates);
- this.ExportedCandidates = new List<TriggerCandidate>(AllCandidates == null ? Enumerable.Empty<TriggerCandidate>() : AllCandidates.Except(this.PrivateCandidates));
- }
-
- public override string ToString() {
- StringBuilder sb = new StringBuilder();
- string indent = " {0}", nindent = "\n - {0}", subindent = "\n * {0}";
-
- sb.AppendFormat(indent, IsTriggerKiller);
-
- sb.AppendFormat(nindent, "Variables:");
- foreach (var bv in Variables) {
- sb.AppendFormat(subindent, bv.Name);
- }
-
- sb.AppendFormat(nindent, "Exported candidates:");
- foreach (var candidate in ExportedCandidates) {
- sb.AppendFormat(subindent, candidate);
- }
-
- if (PrivateCandidates.Any()) {
- sb.AppendFormat(nindent, "Private candidates:");
- foreach (var candidate in PrivateCandidates) {
- sb.AppendFormat(subindent, candidate);
- }
- }
-
- return sb.ToString();
- }
- }
-
- public class TriggerGenerator : BottomUpVisitor {
- List<QuantifierExpr> quantifiers;
- Dictionary<Expression, TriggerAnnotation> annotations;
-
- Action<IToken, string> AdditionalInformationReporter;
-
- private TriggerGenerator(Action<IToken, string> additionalInformationReporter) {
- Contract.Requires(additionalInformationReporter != null);
- this.quantifiers = new List<QuantifierExpr>();
- this.annotations = new Dictionary<Expression, TriggerAnnotation>();
- this.AdditionalInformationReporter = additionalInformationReporter;
- }
-
- private List<T> MergeAlterFirst<T>(List<T> a, List<T> b) {
- Contract.Requires(a != null);
- Contract.Requires(b != null);
- a.AddRange(b);
- return a;
- }
-
- private ISet<T> MergeAlterFirst<T>(ISet<T> a, ISet<T> b) {
- Contract.Requires(a != null);
- Contract.Requires(b != null);
- a.UnionWith(b);
- return a;
- }
-
- private T ReduceAnnotatedSubExpressions<T>(Expression expr, T seed, Func<TriggerAnnotation, T> map, Func<T, T, T> reduce) {
- return expr.SubExpressions.Select(e => map(Annotate(e)))
- .Aggregate(seed, (acc, e) => reduce(acc, e));
- }
-
- private List<TriggerCandidate> CollectExportedCandidates(Expression expr) {
- return ReduceAnnotatedSubExpressions<List<TriggerCandidate>>(expr, new List<TriggerCandidate>(), a => a.ExportedCandidates, MergeAlterFirst);
- }
-
- private ISet<IVariable> CollectVariables(Expression expr) {
- return ReduceAnnotatedSubExpressions(expr, new HashSet<IVariable>(), a => a.Variables, MergeAlterFirst);
- }
-
- private bool CollectIsKiller(Expression expr) {
- return ReduceAnnotatedSubExpressions(expr, false, a => a.IsTriggerKiller, (a, b) => a || b);
- }
-
- private IEnumerable<TriggerCandidate> OnlyPrivateCandidates(List<TriggerCandidate> candidates, IEnumerable<IVariable> privateVars) {
- return candidates.Where(c => privateVars.Intersect(c.Variables).Any()); //TODO Check perf
- }
-
- private TriggerAnnotation Annotate(Expression expr) {
- TriggerAnnotation cached;
- if (annotations.TryGetValue(expr, out cached)) {
- return cached;
- }
-
- expr.SubExpressions.Iter(e => Annotate(e)); //NOTE: These values are all cached
-
- TriggerAnnotation annotation; // TODO: Using ApplySuffix fixes the unresolved members problem in GenericSort
- if (expr is FunctionCallExpr || expr is SeqSelectExpr || expr is MemberSelectExpr || expr is OldExpr ||
- (expr is UnaryOpExpr && (((UnaryOpExpr)expr).Op == UnaryOpExpr.Opcode.Cardinality)) || // FIXME || ((UnaryOpExpr)expr).Op == UnaryOpExpr.Opcode.Fresh oesn't work, as fresh is a pretty tricky predicate when it's not about datatypes. See translator.cs:10944
- (expr is BinaryExpr && (((BinaryExpr)expr).Op == BinaryExpr.Opcode.NotIn || ((BinaryExpr)expr).Op == BinaryExpr.Opcode.In))) {
- annotation = AnnotatePotentialCandidate(expr);
- } else if (expr is QuantifierExpr) {
- annotation = AnnotateQuantifier((QuantifierExpr)expr);
- } else if (expr is LetExpr) {
- annotation = AnnotateLetExpr((LetExpr)expr);
- } else if (expr is IdentifierExpr) {
- annotation = AnnotateIdentifier((IdentifierExpr)expr);
- } else if (expr is ApplySuffix) {
- annotation = AnnotateApplySuffix((ApplySuffix)expr);
- } else if (expr is ConcreteSyntaxExpression ||
- expr is LiteralExpr ||
- expr is OldExpr ||
- expr is ThisExpr ||
- expr is BoxingCastExpr ||
- expr is DatatypeValue) {
- annotation = AnnotateOther(expr, false);
- } else {
- annotation = AnnotateOther(expr, true);
- }
-
- DebugTriggers("{0} ({1})\n{2}", Printer.ExprToString(expr), expr.GetType(), annotation);
- annotations[expr] = annotation;
- return annotation;
- }
-
- [Conditional("DEBUG_AUTO_TRIGGERS")]
- private static void DebugTriggers(string format, params object[] more) {
- Console.Error.WriteLine(format, more);
- }
-
- private BinaryExpr.ResolvedOpcode RemoveNotInBinaryExprIn(BinaryExpr.ResolvedOpcode opcode) {
- switch(opcode) {
- case BinaryExpr.ResolvedOpcode.NotInMap:
- return BinaryExpr.ResolvedOpcode.InMap;
- case BinaryExpr.ResolvedOpcode.NotInSet:
- return BinaryExpr.ResolvedOpcode.InSet;
- case BinaryExpr.ResolvedOpcode.NotInSeq:
- return BinaryExpr.ResolvedOpcode.InSeq;
- case BinaryExpr.ResolvedOpcode.NotInMultiSet:
- return BinaryExpr.ResolvedOpcode.InMultiSet;
- }
-
- Contract.Assert(false);
- throw new ArgumentException();
- }
-
- private Expression CleanupExpr(Expression expr, out bool isKiller) {
- isKiller = false;
-
- if (!(expr is BinaryExpr)) {
- return expr;
- }
-
- var bexpr = expr as BinaryExpr;
-
- BinaryExpr new_expr = bexpr;
- if (bexpr.Op == BinaryExpr.Opcode.NotIn) {
- new_expr = new BinaryExpr(bexpr.tok, BinaryExpr.Opcode.In, bexpr.E0, bexpr.E1);
- new_expr.ResolvedOp = RemoveNotInBinaryExprIn(bexpr.ResolvedOp);
- new_expr.Type = bexpr.Type;
- }
-
- Expression returned_expr = new_expr;
- if (new_expr.ResolvedOp == BinaryExpr.ResolvedOpcode.InMultiSet) {
- returned_expr = new SeqSelectExpr(new_expr.tok, true, new_expr.E1, new_expr.E0, null);
- returned_expr.Type = bexpr.Type;
- isKiller = true; // [a in s] becomes [s[a] > 0], which is a trigger killer
- }
-
- return returned_expr;
- }
-
- private TriggerAnnotation AnnotatePotentialCandidate(Expression expr) {
- bool expr_is_killer = false;
- var new_expr = CleanupExpr(expr, out expr_is_killer);
- var new_candidate = new TriggerCandidate { Expr = new_expr, Variables = CollectVariables(expr) };
-
- List<TriggerCandidate> collected_candidates = CollectExportedCandidates(expr);
- var children_contain_killers = CollectIsKiller(expr);
-
- if (!children_contain_killers) {
- // Add only if the children are not killers; the head has been cleaned up into non-killer form
- collected_candidates.Add(new_candidate);
- }
-
- // This new node is a killer if its children were killers, or if it's non-cleaned-up head is a killer
- return new TriggerAnnotation(children_contain_killers || expr_is_killer, new_candidate.Variables, collected_candidates);
- }
-
- private TriggerAnnotation AnnotateApplySuffix(ApplySuffix expr) {
- // This is a bit tricky. A funcall node is generally meaningful as a trigger candidate,
- // but when it's part of an ApplySuffix the function call itself may not resolve properly
- // when the second round of resolving is done after modules are duplicated.
- // Thus first we annotate expr and create a trigger candidate, and then we remove the
- // candidate matching its direct subexpression if needed. Not that function calls are not the
- // only possible child here; there can be DatatypeValue nodes, for example (see vstte2012/Combinators.dfy).
- var annotation = AnnotatePotentialCandidate(expr);
- // Comparing by reference is fine here. Using sets could yield a small speedup
- annotation.ExportedCandidates.RemoveAll(candidate => expr.SubExpressions.Contains(candidate.Expr));
- return annotation;
- }
-
- private TriggerAnnotation AnnotateQuantifierOrLetExpr(Expression expr, IEnumerable<BoundVar> boundVars) {
- var candidates = CollectExportedCandidates(expr);
- return new TriggerAnnotation(true, CollectVariables(expr), candidates, OnlyPrivateCandidates(candidates, boundVars));
- }
-
- private TriggerAnnotation AnnotateQuantifier(QuantifierExpr expr) {
- quantifiers.Add(expr);
- return AnnotateQuantifierOrLetExpr(expr, expr.BoundVars);
- }
-
- private TriggerAnnotation AnnotateLetExpr(LetExpr expr) {
- return AnnotateQuantifierOrLetExpr(expr, expr.BoundVars);
- }
-
- private TriggerAnnotation AnnotateIdentifier(IdentifierExpr expr) {
- return new TriggerAnnotation(false, Enumerable.Repeat(expr.Var, 1), null);
- }
-
- private TriggerAnnotation AnnotateOther(Expression expr, bool isTriggerKiller) {
- return new TriggerAnnotation(isTriggerKiller || CollectIsKiller(expr), CollectVariables(expr), CollectExportedCandidates(expr));
- }
-
- private static List<T> CopyAndAdd<T>(List<T> seq, T elem) {
- var copy = new List<T>(seq);
- copy.Add(elem);
- return copy;
- }
-
- private static IEnumerable<List<T>> AllSubsets<T>(IList<T> source, int offset) {
- if (offset >= source.Count) {
- yield return new List<T>();
- yield break;
- }
-
- foreach (var subset in AllSubsets<T>(source, offset + 1)) {
- yield return CopyAndAdd(subset, source[offset]);
- yield return new List<T>(subset);
- }
- }
-
- private static IEnumerable<List<T>> AllNonEmptySubsets<T>(IEnumerable<T> source) {
- List<T> all = new List<T>(source);
- foreach (var subset in AllSubsets(all, 0)) {
- if (subset.Count > 0) {
- yield return subset;
- }
- }
- }
-
- private static bool DefaultCandidateFilteringFunction(TriggerCandidate candidate, QuantifierExpr quantifier) {
- //FIXME this will miss rewritten expressions (CleanupExpr). Should introduce an OriginalExpr to compare.
- candidate.MatchesInQuantifierBody = quantifier.SubexpressionsMatchingTrigger(candidate.Expr).ToList();
- return true;
- }
-
- private static bool DefaultMultiCandidateFilteringFunction(MultiTriggerCandidate multiCandidate, QuantifierExpr quantifier) {
- var allowsLoops = quantifier.Attributes.AsEnumerable().Any(a => a.Name == "loop");
-
- if (!allowsLoops && multiCandidate.PotentialMatchingLoops.Any()) {
- multiCandidate.Tags.Add(String.Format("matching loop with {0}", multiCandidate.PotentialMatchingLoops.MapConcat(tm => Printer.ExprToString(tm.Expr), ", ")));
- }
- return multiCandidate.MentionsAll(quantifier.BoundVars) && (allowsLoops || !multiCandidate.PotentialMatchingLoops.Any());
- }
-
- private static double DefaultMultiCandidateScoringFunction(MultiTriggerCandidate multi_candidate) {
- return 1.0;
- }
-
- private static IEnumerable<MultiTriggerCandidate> DefaultMultiCandidateSelectionFunction(List<MultiTriggerCandidate> multi_candidates) {
- return multi_candidates;
- }
-
- // CLEMENT: Make these customizable
- internal Func<TriggerCandidate, QuantifierExpr, bool> CandidateFilteringFunction = DefaultCandidateFilteringFunction;
- internal Func<MultiTriggerCandidate, QuantifierExpr, bool> MultiCandidateFilteringFunction = DefaultMultiCandidateFilteringFunction;
- internal Func<MultiTriggerCandidate, double> MultiCandidateScoringFunction = DefaultMultiCandidateScoringFunction;
- internal Func<List<MultiTriggerCandidate>, IEnumerable<MultiTriggerCandidate>> MultiCandidateSelectionFunction = DefaultMultiCandidateSelectionFunction;
-
- struct MultiCandidatesCollection {
- internal List<TriggerCandidate> AllCandidates;
- internal List<TriggerCandidate> SelectedCandidates;
- internal List<TriggerCandidate> RejectedCandidates;
- internal List<MultiTriggerCandidate> SelectedMultiCandidates;
- internal List<MultiTriggerCandidate> RejectedMultiCandidates;
- internal List<MultiTriggerCandidate> FinalMultiCandidates;
-
- public MultiCandidatesCollection(QuantifierExpr quantifier,
- TriggerAnnotation annotation,
- Func<TriggerCandidate, QuantifierExpr, bool> CandidateFilteringFunction,
- Func<MultiTriggerCandidate, QuantifierExpr, bool> MultiCandidateFilteringFunction,
- Func<MultiTriggerCandidate, double> MultiCandidateScoringFunction,
- Func<List<MultiTriggerCandidate>, IEnumerable<MultiTriggerCandidate>> MultiCandidateSelectionFunction) {
-
- Contract.Requires(annotation != null);
- Contract.Requires(quantifier != null);
- Contract.Requires(CandidateFilteringFunction != null);
- Contract.Requires(MultiCandidateFilteringFunction != null);
- Contract.Requires(MultiCandidateScoringFunction != null);
- Contract.Requires(MultiCandidateSelectionFunction != null);
-
- AllCandidates = annotation.PrivateCandidates.Deduplicate((x, y) => ExprExtensions.ExpressionEq(x.Expr, y.Expr));
- Partition(AllCandidates,
- x => CandidateFilteringFunction(x, quantifier), out SelectedCandidates, out RejectedCandidates);
- Partition(AllNonEmptySubsets(SelectedCandidates).Select(s => new MultiTriggerCandidate(s)),
- x => MultiCandidateFilteringFunction(x, quantifier), out SelectedMultiCandidates, out RejectedMultiCandidates);
- SelectedMultiCandidates.Iter(x => x.Score = MultiCandidateScoringFunction(x));
- FinalMultiCandidates = MultiCandidateSelectionFunction(SelectedMultiCandidates).ToList();
- }
-
- private static void Partition<T>(IEnumerable<T> elements, Func<T, bool> predicate, out List<T> positive, out List<T> negative) {
- positive = new List<T>();
- negative = new List<T>();
- foreach (var c in elements) {
- (predicate(c) ? positive : negative).Add(c);
- }
- }
-
- internal string Warning() {
- if (AllCandidates.Count == 0) {
- return "No triggers found in the body of this quantifier.";
- } else if (SelectedCandidates.Count == 0) {
- return String.Format("No suitable triggers found. Candidate building blocks for a good trigger where [{0}], but none these terms passed the initial selection stage.", String.Join(", ", AllCandidates));
- } else if (SelectedMultiCandidates.Count == 0) {
- return String.Format("No suitable set of triggers found. Candidate building blocks for a good trigger where [{0}], but no subset of these terms passed the subset selection stage.", String.Join(", ", SelectedCandidates));
- } else if (FinalMultiCandidates.Count == 0) {
- return String.Format("No suitable set of triggers found. Candidates where [{0}], but none passed the final selection stage.", String.Join(", ", SelectedMultiCandidates));
- } else {
- return null;
- }
- }
-
- private void WriteIndented<T>(StringBuilder builder, string indent, IEnumerable<T> elements) {
- foreach (var element in elements) {
- builder.Append(indent).AppendLine(element.ToString());
- }
- }
-
- private void WriteListOfCandidates<T>(StringBuilder builder, string indent, IEnumerable<T> elements) {
- if (elements.Any()) {
- builder.AppendLine();
- WriteIndented(builder, indent, elements);
- } else {
- builder.AppendLine(" (None)");
- }
- }
-
- public override string ToString() {
- var repr = new StringBuilder();
- var indent = " ";
- repr.Append(" All:");
- WriteListOfCandidates(repr, indent, AllCandidates);
- repr.Append(" Selected1:");
- WriteListOfCandidates(repr, indent, SelectedCandidates);
- repr.Append(" PreFilter:");
- WriteListOfCandidates(repr, indent, AllNonEmptySubsets(AllCandidates).Select(c => String.Join(", ", c)));
- repr.Append(" SelectedMulti:");
- WriteListOfCandidates(repr, indent, SelectedMultiCandidates.Select(c => String.Join(", ", c)));
- repr.Append(" Final:");
- WriteListOfCandidates(repr, indent, FinalMultiCandidates);
- return repr.ToString();
- }
- }
-
- private MultiCandidatesCollection PickMultiTriggers(QuantifierExpr quantifier) {
- var annotation = Annotate(quantifier);
- DebugTriggers("Quantifier {0}:\n{1}", Printer.ExprToString(quantifier), annotation);
- return new MultiCandidatesCollection(quantifier, annotation, CandidateFilteringFunction, MultiCandidateFilteringFunction, MultiCandidateScoringFunction, MultiCandidateSelectionFunction);
- }
-
- private void AddTrigger(QuantifierExpr quantifier) {
- DebugTriggers(" Final results:\n{0}", PickMultiTriggers(quantifier));
-
- if (quantifier.Attributes.AsEnumerable().Any(aa => aa.Name == "trigger" || aa.Name == "no_trigger")) {
- DebugTriggers("Not generating triggers for {0}", Printer.ExprToString(quantifier)); //FIXME: no_trigger is passed down to Boogie
- return;
- }
-
- var multi_candidates = PickMultiTriggers(quantifier);
- foreach (var multi_candidate in multi_candidates.FinalMultiCandidates) { //TODO: error message for when no triggers found
- quantifier.Attributes = new Attributes("trigger", multi_candidate.Candidates.Select(t => t.Expr).ToList(), quantifier.Attributes);
- }
-
- if (multi_candidates.RejectedMultiCandidates.Any()) {
- var tooltip = JoinStringsWithHeader("Rejected: ", multi_candidates.RejectedMultiCandidates.Where(candidate => candidate.Tags != null)
- .Select(candidate => candidate.AsDafnyAttributeString(true, true)));
- AdditionalInformationReporter(quantifier.tok, tooltip);
- }
-
- if (multi_candidates.FinalMultiCandidates.Any()) {
- var tooltip = JoinStringsWithHeader("Triggers: ", multi_candidates.FinalMultiCandidates.Select(multi_candidate => multi_candidate.AsDafnyAttributeString()));
- AdditionalInformationReporter(quantifier.tok, tooltip);
- }
-
- string warning = multi_candidates.Warning();
- if (warning != null) {
- // FIXME reenable Resolver.Warning(quantifier.tok, warning);
- }
- }
-
- internal static bool IsTriggerKiller(Expression expr) {
- var annotation = new TriggerGenerator((x, y) => { }).Annotate(expr);
- return annotation.IsTriggerKiller;
- }
-
- private string JoinStringsWithHeader(string header, IEnumerable<string> lines) {
- return header + String.Join(Environment.NewLine + new String(' ', header.Length), lines);
- }
-
- private void AddTriggers_Internal() {
- foreach (var quantifier in quantifiers) {
- AddTrigger(quantifier);
- }
- }
-
- private void AddTriggers_Internal(Expression root) {
- Visit(root);
- AddTriggers_Internal();
- }
-
- private void AddTriggers_Internal(Statement root) {
- Visit(root);
- AddTriggers_Internal();
- }
-
- internal static void AddTriggers(Expression root, Resolver resolver) {
- if (root == null)
- return;
-
- DebugTriggers("== From {0} visiting expr: {1}", new StackFrame(1).GetMethod().Name, Printer.ExprToString(root));
- TriggerGenerator generator = new TriggerGenerator(resolver.ReportAdditionalInformation);
- generator.AddTriggers_Internal(root);
- }
-
- internal static void AddTriggers(Statement root, Resolver resolver) {
- if (root == null)
- return;
-
- DebugTriggers("== From {0} visiting statement: {1}", new StackFrame(1).GetMethod().Name, Printer.StatementToString(root));
- TriggerGenerator generator = new TriggerGenerator(resolver.ReportAdditionalInformation);
- generator.AddTriggers_Internal(root);
- }
-
- internal static void AddTriggers(IEnumerable<Expression> roots, Resolver resolver) {
- DebugTriggers("== From {0} visiting expressions: {1}", new StackFrame(1).GetMethod().Name,
- roots.MapConcat(Printer.ExprToString, ", "));
- foreach (var expr in roots) {
- AddTriggers(expr, resolver);
- }
- }
-
- internal static void AddTriggers(IEnumerable<MaybeFreeExpression> roots, Resolver resolver) {
- DebugTriggers("== From {0} visiting expressions: {1}", new StackFrame(1).GetMethod().Name,
- roots.MapConcat(root => Printer.ExprToString(root.E), ", "));
- foreach (var expr in roots) {
- AddTriggers(expr.E, resolver);
- }
- }
-
- protected override void VisitOneExpr(Expression expr) {
- Annotate(expr);
- }
- }
-
- internal static class DeduplicateExtension {
- public static List<T> Deduplicate<T>(this IEnumerable<T> seq, Func<T, T, bool> eq) {
- List<T> deduplicated = new List<T>();
-
- foreach (var elem in seq) {
- if (!deduplicated.Any(other => eq(elem, other))) {
- deduplicated.Add(elem);
- }
- }
-
- return deduplicated;
- }
- }
-
- static class ExprExtensions {
- static IEnumerable<Expression> AllSubExpressions(this Expression expr, bool strict = false) {
- foreach (var subexpr in expr.SubExpressions) {
- foreach (var r_subexpr in AllSubExpressions(subexpr, false)) {
- yield return r_subexpr;
- }
- yield return subexpr;
- }
-
- if (expr is StmtExpr) {
- foreach (var r_subexpr in AllSubExpressions(((StmtExpr)expr).S, false)) {
- yield return r_subexpr;
- }
- }
-
- if (!strict) {
- yield return expr;
- }
- }
-
- private static IEnumerable<Expression> AllSubExpressions(this Statement stmt, bool strict = false) {
- foreach (var subexpr in stmt.SubExpressions) {
- foreach (var r_subexpr in AllSubExpressions(subexpr, false)) {
- yield return r_subexpr;
- }
- yield return subexpr;
- }
-
- foreach (var substmt in stmt.SubStatements) {
- foreach (var r_subexpr in AllSubExpressions(substmt, false)) {
- yield return r_subexpr;
- }
- }
- }
-
- internal static bool ExpressionEq(this Expression expr1, Expression expr2) {
- expr1 = GetResolved(expr1);
- expr2 = GetResolved(expr2);
-
- return ShallowEq_Top(expr1, expr2) && SameLists(expr1.SubExpressions, expr2.SubExpressions, (e1, e2) => ExpressionEq(e1, e2));
- }
-
- internal static bool ExpressionEqModuloVariableNames(this Expression expr1, Expression expr2) {
- expr1 = GetResolved(expr1);
- expr2 = GetResolved(expr2);
-
- if (expr1 is IdentifierExpr) {
- return expr2 is IdentifierExpr;
- }
-
- return ShallowEq_Top(expr1, expr2) && SameLists(expr1.SubExpressions, expr2.SubExpressions, (e1, e2) => ExpressionEqModuloVariableNames(e1, e2));
- }
-
- private static bool MatchesTrigger(this Expression expr, Expression trigger, ISet<BoundVar> holes, Dictionary<IVariable, Expression> bindings) {
- expr = GetResolved(expr);
- trigger = GetResolved(trigger);
-
- if (trigger is IdentifierExpr) {
- var var = ((IdentifierExpr)trigger).Var;
-
- if (holes.Contains(var)) {
- Expression existing_binding = null;
- if (bindings.TryGetValue(var, out existing_binding)) {
- return ExpressionEq(expr, existing_binding);
- } else {
- bindings[var] = expr;
- return true;
- }
- }
- }
-
- return ShallowEq_Top(expr, trigger) && SameLists(expr.SubExpressions, trigger.SubExpressions, (e1, e2) => MatchesTrigger(e1, e2, holes, bindings));
- }
-
- internal struct TriggerMatch {
- internal Expression Expr;
- internal Dictionary<IVariable, Expression> Bindings;
-
- internal bool CouldCauseLoops(IEnumerable<TriggerCandidate> candidates) {
- // A match for a trigger in the body of a quantifier can be a problem if
- // it yields to a matching loop: for example, f(x) is a bad trigger in
- // forall x, y :: f(x) = f(f(x))
- // In general, any such match can lead to a loop, but two special cases
- // will only lead to a finite number of instantiations:
- // 1. The match equals one of the triggers in the set of triggers under
- // consideration. For example, { f(x) } a bad trigger above, but the
- // pair { f(x), f(f(x)) } is fine (instantiating won't yield new
- // matches)
- // 2. The match only differs from one of these triggers by variable
- // names. This is a superset of the previous case.
- var expr = Expr;
- return !candidates.Any(c => c.Expr.ExpressionEqModuloVariableNames(expr));
- }
- }
-
- private static TriggerMatch? MatchAgainst(this Expression expr, Expression trigger, ISet<BoundVar> holes) {
- var bindings = new Dictionary<IVariable, Expression>();
- return expr.MatchesTrigger(trigger, holes, bindings) ? new TriggerMatch { Expr = expr, Bindings = bindings } : (TriggerMatch?)null;
- }
-
- internal static IEnumerable<TriggerMatch> SubexpressionsMatchingTrigger(this QuantifierExpr quantifier, Expression trigger) {
- return quantifier.Term.AllSubExpressions()
- .Select(e => e.MatchAgainst(trigger, new HashSet<BoundVar>(quantifier.BoundVars)))
- .Where(e => e.HasValue).Select(e => e.Value);
- }
-
- private static bool SameLists<T>(IEnumerable<T> list1, IEnumerable<T> list2, Func<T, T, bool> comparer) {
- if (ReferenceEquals(list1, list2)) {
- return true;
- } else if ((list1 == null) != (list2 == null)) {
- return false;
- }
-
- var it1 = list1.GetEnumerator();
- var it2 = list2.GetEnumerator();
- bool it1_has, it2_has;
- bool acc = true;
-
- do {
- it1_has = it1.MoveNext();
- it2_has = it2.MoveNext();
-
- if (it1_has == true && it2_has == true) {
- acc = acc && comparer(it1.Current, it2.Current);
- }
- } while (it1_has && it2_has);
-
- return it1_has == it2_has && acc;
- }
-
- private static bool SameNullity<T>(T x1, T x2) where T : class {
- return (x1 == null) == (x2 == null);
- }
-
- private static bool ShallowSameAttributes(Attributes attributes1, Attributes attributes2) {
- return SameLists(attributes1.AsEnumerable(), attributes2.AsEnumerable(), ShallowSameSingleAttribute);
- }
-
- private static bool ShallowSameSingleAttribute(Attributes arg1, Attributes arg2) {
- return arg1.Name == arg2.Name;
- }
-
- private static bool SameBoundVar(IVariable arg1, IVariable arg2) {
- return arg1 == arg2 ||
- (arg1.Name == arg2.Name &&
- arg1.CompileName == arg2.CompileName &&
- arg1.DisplayName == arg2.DisplayName &&
- arg1.UniqueName == arg2.UniqueName &&
- arg1.IsGhost == arg2.IsGhost &&
- arg1.IsMutable == arg2.IsMutable); //FIXME compare types?
- }
-
- private static Expression GetResolved(Expression expr) {
- if (expr is ConcreteSyntaxExpression) {
- return ((ConcreteSyntaxExpression)expr).ResolvedExpression;
- }
- return expr;
- }
-
- /// <summary>
- /// Compares two abstract syntax expressions, looking only at their direct members. Subexpressions and substatements are not compared.
- /// </summary>
- /// <returns></returns>
- internal static bool ShallowEq_Top(Expression expr1, Expression expr2) {
- Contract.Requires(expr1 != null);
- Contract.Requires(expr2 != null);
-
- // We never compare concrete expressions
- Contract.Requires(!(expr1 is ConcreteSyntaxExpression));
- Contract.Requires(!(expr2 is ConcreteSyntaxExpression));
-
- // CPC: Hey future editor: the following block of code is auto-generated. Just add your own cases at the end.
- // This could be a visitor pattern, except I need to visit a pair of nodes.
- // It could also be implemented in each individual class. I'd have a slight preference for that.
- // This really just wants to use double dispatch.
- if (expr1 is UnboxingCastExpr && expr2 is UnboxingCastExpr) {
- return ShallowEq((UnboxingCastExpr)expr1, (UnboxingCastExpr)expr2);
- } else if (expr1 is BoxingCastExpr && expr2 is BoxingCastExpr) {
- return ShallowEq((BoxingCastExpr)expr1, (BoxingCastExpr)expr2);
- } else if (expr1 is MatchExpr && expr2 is MatchExpr) {
- return ShallowEq((MatchExpr)expr1, (MatchExpr)expr2);
- } else if (expr1 is ITEExpr && expr2 is ITEExpr) {
- return ShallowEq((ITEExpr)expr1, (ITEExpr)expr2);
- } else if (expr1 is StmtExpr && expr2 is StmtExpr) {
- return ShallowEq((StmtExpr)expr1, (StmtExpr)expr2);
- } else if (expr1 is WildcardExpr && expr2 is WildcardExpr) {
- return ShallowEq((WildcardExpr)expr1, (WildcardExpr)expr2);
- } else if (expr1 is ComprehensionExpr && expr2 is ComprehensionExpr) {
- return ShallowEq((ComprehensionExpr)expr1, (ComprehensionExpr)expr2);
- } else if (expr1 is NamedExpr && expr2 is NamedExpr) {
- return ShallowEq((NamedExpr)expr1, (NamedExpr)expr2);
- } else if (expr1 is LetExpr && expr2 is LetExpr) {
- return ShallowEq((LetExpr)expr1, (LetExpr)expr2);
- } else if (expr1 is TernaryExpr && expr2 is TernaryExpr) {
- return ShallowEq((TernaryExpr)expr1, (TernaryExpr)expr2);
- } else if (expr1 is BinaryExpr && expr2 is BinaryExpr) {
- return ShallowEq((BinaryExpr)expr1, (BinaryExpr)expr2);
- } else if (expr1 is UnaryExpr && expr2 is UnaryExpr) {
- return ShallowEq((UnaryExpr)expr1, (UnaryExpr)expr2);
- } else if (expr1 is MultiSetFormingExpr && expr2 is MultiSetFormingExpr) {
- return ShallowEq((MultiSetFormingExpr)expr1, (MultiSetFormingExpr)expr2);
- } else if (expr1 is OldExpr && expr2 is OldExpr) {
- return ShallowEq((OldExpr)expr1, (OldExpr)expr2);
- } else if (expr1 is FunctionCallExpr && expr2 is FunctionCallExpr) {
- return ShallowEq((FunctionCallExpr)expr1, (FunctionCallExpr)expr2);
- } else if (expr1 is ApplyExpr && expr2 is ApplyExpr) {
- return ShallowEq((ApplyExpr)expr1, (ApplyExpr)expr2);
- } else if (expr1 is SeqUpdateExpr && expr2 is SeqUpdateExpr) {
- return ShallowEq((SeqUpdateExpr)expr1, (SeqUpdateExpr)expr2);
- } else if (expr1 is MultiSelectExpr && expr2 is MultiSelectExpr) {
- return ShallowEq((MultiSelectExpr)expr1, (MultiSelectExpr)expr2);
- } else if (expr1 is SeqSelectExpr && expr2 is SeqSelectExpr) {
- return ShallowEq((SeqSelectExpr)expr1, (SeqSelectExpr)expr2);
- } else if (expr1 is MemberSelectExpr && expr2 is MemberSelectExpr) {
- return ShallowEq((MemberSelectExpr)expr1, (MemberSelectExpr)expr2);
- } else if (expr1 is MapDisplayExpr && expr2 is MapDisplayExpr) { //Note: MapDisplayExpr is not a DisplayExpression
- return ShallowEq((MapDisplayExpr)expr1, (MapDisplayExpr)expr2);
- } else if (expr1 is DisplayExpression && expr2 is DisplayExpression) {
- return ShallowEq((DisplayExpression)expr1, (DisplayExpression)expr2);
- } else if (expr1 is IdentifierExpr && expr2 is IdentifierExpr) {
- return ShallowEq((IdentifierExpr)expr1, (IdentifierExpr)expr2);
- } else if (expr1 is ThisExpr && expr2 is ThisExpr) {
- return ShallowEq((ThisExpr)expr1, (ThisExpr)expr2);
- } else if (expr1 is DatatypeValue && expr2 is DatatypeValue) {
- return ShallowEq((DatatypeValue)expr1, (DatatypeValue)expr2);
- } else if (expr1 is LiteralExpr && expr2 is LiteralExpr) {
- return ShallowEq((LiteralExpr)expr1, (LiteralExpr)expr2);
- } else {
- // If this assertion fail, then a new abstract AST node was probably introduced but not registered here.
- Contract.Assert(expr1.GetType() != expr2.GetType());
- return false;
- }
- }
-
- private static bool ShallowEq(UnboxingCastExpr expr1, UnboxingCastExpr expr2) {
- Contract.Requires(false);
- throw new InvalidOperationException();
- }
-
- private static bool ShallowEq(BoxingCastExpr expr1, BoxingCastExpr expr2) {
- return expr1.FromType == expr2.FromType &&
- expr1.ToType == expr2.ToType;
- }
-
- private static bool ShallowEq(MatchExpr expr1, MatchExpr expr2) {
- return true;
- }
-
- private static bool ShallowEq(ITEExpr expr1, ITEExpr expr2) {
- return true;
- }
-
- private static bool ShallowEq(StmtExpr expr1, StmtExpr expr2) {
-#if THROW_UNSUPPORTED_COMPARISONS
- Contract.Assume(false); // This kind of expression never appears in a trigger
- throw new NotImplementedException();
-#else
- return expr1.S == expr2.S;
-#endif
- }
-
- private static bool ShallowEq(WildcardExpr expr1, WildcardExpr expr2) {
- return true;
- }
-
- private static bool ShallowEq(LambdaExpr expr1, LambdaExpr expr2) {
-#if THROW_UNSUPPORTED_COMPARISONS
- Contract.Assume(false); // This kind of expression never appears in a trigger
- throw new NotImplementedException();
-#else
- return expr1.OneShot == expr2.OneShot &&
- SameLists(expr1.Reads, expr2.Reads, SameFrameExpression);
-#endif
- }
-
- private static bool ShallowEq(MapComprehension expr1, MapComprehension expr2) {
- return expr1.Finite == expr2.Finite;
- }
-
- private static bool ShallowEq(SetComprehension expr1, SetComprehension expr2) {
- return expr1.TermIsImplicit == expr2.TermIsImplicit && //TODO
- expr1.Finite == expr2.Finite;
- }
-
- private static bool ShallowEq(ExistsExpr expr1, ExistsExpr expr2) {
- return true;
- }
-
- private static bool ShallowEq(ForallExpr expr1, ForallExpr expr2) {
- return true;
- }
-
- private static bool ShallowEq(QuantifierExpr expr1, QuantifierExpr expr2) { //FIXME are these TypeArgs still useful?
- if (expr1.TypeArgs.Count != expr2.TypeArgs.Count ||
- !SameNullity(expr1.Range, expr2.Range)) {
- return false;
- }
-
- if (expr1 is ExistsExpr && expr2 is ExistsExpr) {
- return ShallowEq((ExistsExpr)expr1, (ExistsExpr)expr2);
- } else if (expr1 is ForallExpr && expr2 is ForallExpr) {
- return ShallowEq((ForallExpr)expr1, (ForallExpr)expr2);
- } else {
- return false;
- }
- }
-
- private static bool ShallowEq(ComprehensionExpr expr1, ComprehensionExpr expr2) {
- if (!SameLists(expr1.BoundVars, expr2.BoundVars, SameBoundVar) ||
- !ShallowSameAttributes(expr1.Attributes, expr2.Attributes) ||
- // Filled in during resolution: !SameLists(expr1.Bounds, expr2.Bounds, ReferenceCompare) ||
- // !SameLists(expr1.MissingBounds, expr2.MissingBounds, SameBoundVar) ||
- !SameNullity(expr1.Range, expr2.Range)) { //TODO Check
- return false;
- }
-
- if (expr1 is LambdaExpr && expr2 is LambdaExpr) {
- return ShallowEq((LambdaExpr)expr1, (LambdaExpr)expr2);
- } else if (expr1 is MapComprehension && expr2 is MapComprehension) {
- return ShallowEq((MapComprehension)expr1, (MapComprehension)expr2);
- } else if (expr1 is SetComprehension && expr2 is SetComprehension) {
- return ShallowEq((SetComprehension)expr1, (SetComprehension)expr2);
- } else if (expr1 is QuantifierExpr && expr2 is QuantifierExpr) {
- return ShallowEq((QuantifierExpr)expr1, (QuantifierExpr)expr2);
- } else {
- return false; // ComprehensionExpr is abstract
- }
- }
-
- private static bool ShallowEq(NamedExpr expr1, NamedExpr expr2) {
- return expr1.Name == expr2.Name &&
- SameNullity(expr1.Contract, expr2.Contract);
- }
-
- private static bool ShallowEq(LetExpr expr1, LetExpr expr2) {
- return expr1.Exact == expr2.Exact &&
- ShallowSameAttributes(expr1.Attributes, expr2.Attributes);
- }
-
- private static bool ShallowEq(TernaryExpr expr1, TernaryExpr expr2) {
- return expr1.Op == expr2.Op;
- }
-
- private static bool ShallowEq(BinaryExpr expr1, BinaryExpr expr2) {
- Contract.Requires(expr1.ResolvedOp != BinaryExpr.ResolvedOpcode.YetUndetermined);
- Contract.Requires(expr2.ResolvedOp != BinaryExpr.ResolvedOpcode.YetUndetermined);
- return expr1.ResolvedOp == expr2.ResolvedOp;
- }
-
- private static bool ShallowEq(ConversionExpr expr1, ConversionExpr expr2) {
- return expr1.Type == expr2.Type; //TODO equality on types?
- }
-
- private static bool ShallowEq(UnaryOpExpr expr1, UnaryOpExpr expr2) {
- return expr1.Op == expr2.Op;
- }
-
- private static bool ShallowEq(UnaryExpr expr1, UnaryExpr expr2) {
- if (expr1 is ConversionExpr && expr2 is ConversionExpr) {
- return ShallowEq((ConversionExpr)expr1, (ConversionExpr)expr2);
- } else if (expr1 is UnaryOpExpr && expr2 is UnaryOpExpr) {
- return ShallowEq((UnaryOpExpr)expr1, (UnaryOpExpr)expr2);
- } else {
- return false; // UnaryExpr is abstract
- }
- }
-
- private static bool ShallowEq(MultiSetFormingExpr expr1, MultiSetFormingExpr expr2) {
- return true;
- }
-
- private static bool ShallowEq(OldExpr expr1, OldExpr expr2) {
- return true;
- }
-
- private static bool ShallowEq(FunctionCallExpr expr1, FunctionCallExpr expr2) {
- return expr1.Name == expr2.Name &&
- expr1.CoCall == expr2.CoCall && //TODO
- expr1.Function == expr2.Function; // TODO TypeArgumentSubstitutions?
- }
-
- private static bool ShallowEq(ApplyExpr expr1, ApplyExpr expr2) {
- return true;
- }
-
- private static bool ShallowEq(SeqUpdateExpr expr1, SeqUpdateExpr expr2) {
- Contract.Requires(expr1.ResolvedUpdateExpr != null && expr2.ResolvedUpdateExpr != null);
- return true;
- }
-
- private static bool ShallowEq(MultiSelectExpr expr1, MultiSelectExpr expr2) {
- return true;
- }
-
- private static bool ShallowEq(SeqSelectExpr expr1, SeqSelectExpr expr2) {
- return expr1.SelectOne == expr2.SelectOne &&
- SameNullity(expr1.Seq, expr2.Seq) &&
- SameNullity(expr1.E0, expr2.E0) &&
- SameNullity(expr1.E1, expr2.E1);
- }
-
- private static bool ShallowEq(MemberSelectExpr expr1, MemberSelectExpr expr2) {
- return expr1.MemberName == expr2.MemberName &&
- expr1.Member == expr2.Member &&
- SameLists(expr1.TypeApplication, expr2.TypeApplication, Type.Equals);
- }
-
- private static bool ShallowEq(SeqDisplayExpr expr1, SeqDisplayExpr expr2) {
- return true;
- }
-
- private static bool ShallowEq(MapDisplayExpr expr1, MapDisplayExpr expr2) {
- return expr1.Finite == expr2.Finite;
- }
-
- private static bool ShallowEq(MultiSetDisplayExpr expr1, MultiSetDisplayExpr expr2) {
- return true;
- }
-
- private static bool ShallowEq(SetDisplayExpr expr1, SetDisplayExpr expr2) {
- return expr1.Finite == expr2.Finite;
- }
-
- private static bool ShallowEq(DisplayExpression expr1, DisplayExpression expr2) {
- if (expr1 is SeqDisplayExpr && expr2 is SeqDisplayExpr) {
- return ShallowEq((SeqDisplayExpr)expr1, (SeqDisplayExpr)expr2);
- } else if (expr1 is MultiSetDisplayExpr && expr2 is MultiSetDisplayExpr) {
- return ShallowEq((MultiSetDisplayExpr)expr1, (MultiSetDisplayExpr)expr2);
- } else if (expr1 is SetDisplayExpr && expr2 is SetDisplayExpr) {
- return ShallowEq((SetDisplayExpr)expr1, (SetDisplayExpr)expr2);
- } else {
- return false;
- }
- }
-
- private static bool ShallowEq(AutoGhostIdentifierExpr expr1, AutoGhostIdentifierExpr expr2) {
- return true;
- }
-
- private static bool ShallowEq(IdentifierExpr expr1, IdentifierExpr expr2) {
- if (expr1.Name != expr2.Name ||
- expr1.Var != expr2.Var) {
- return false;
- }
-
- if (expr1 is AutoGhostIdentifierExpr && expr2 is AutoGhostIdentifierExpr) {
- return ShallowEq((AutoGhostIdentifierExpr)expr1, (AutoGhostIdentifierExpr)expr2);
- } else {
- return true;
- }
- }
-
- private static bool ShallowEq(ImplicitThisExpr expr1, ImplicitThisExpr expr2) {
- return true;
- }
-
- private static bool ShallowEq(ThisExpr expr1, ThisExpr expr2) {
- if (expr1 is ImplicitThisExpr && expr2 is ImplicitThisExpr) {
- return ShallowEq((ImplicitThisExpr)expr1, (ImplicitThisExpr)expr2);
- } else {
- return (expr1.GetType() == expr2.GetType()); // LiteralExpr is not abstract
- }
- }
-
- private static bool ShallowEq(DatatypeValue expr1, DatatypeValue expr2) {
- return // Implied by Ctor equality: expr1.DatatypeName == expr2.DatatypeName &&
- // Implied by Ctor equality: expr1.MemberName == expr2.MemberName &&
- expr1.Ctor == expr2.Ctor &&
- // Contextual information: expr1.IsCoCall == expr2.IsCoCall &&
- SameLists(expr1.InferredTypeArgs, expr2.InferredTypeArgs, Type.Equals);
- }
-
- private static bool ShallowEq(StringLiteralExpr expr1, StringLiteralExpr expr2) {
- return true;
- }
-
- private static bool ShallowEq(CharLiteralExpr expr1, CharLiteralExpr expr2) {
- return true;
- }
-
- private static bool ShallowEq(StaticReceiverExpr expr1, StaticReceiverExpr expr2) {
- return true;
- }
-
- private static bool ShallowEq(LiteralExpr expr1, LiteralExpr expr2) {
- if (expr1.Value != expr2.Value) {
- return false;
- }
-
- if (expr1 is StringLiteralExpr && expr2 is StringLiteralExpr) {
- return ShallowEq((StringLiteralExpr)expr1, (StringLiteralExpr)expr2);
- } else if (expr1 is CharLiteralExpr && expr2 is CharLiteralExpr) {
- return ShallowEq((CharLiteralExpr)expr1, (CharLiteralExpr)expr2);
- } else if (expr1 is StaticReceiverExpr && expr2 is StaticReceiverExpr) {
- return ShallowEq((StaticReceiverExpr)expr1, (StaticReceiverExpr)expr2);
- } else {
- return (expr1.GetType() == expr2.GetType()); // LiteralExpr is not abstract
- }
- }
- }
-}
diff --git a/Source/Dafny/Triggers/QuantifierSplitter.cs b/Source/Dafny/Triggers/QuantifierSplitter.cs new file mode 100644 index 00000000..4b223856 --- /dev/null +++ b/Source/Dafny/Triggers/QuantifierSplitter.cs @@ -0,0 +1,95 @@ +using Microsoft.Boogie;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Microsoft.Dafny.Triggers {
+ class QuantifierSplitter : BottomUpVisitor {
+ private static BinaryExpr.Opcode FlipOpcode(BinaryExpr.Opcode opCode) {
+ if (opCode == BinaryExpr.Opcode.And) {
+ return BinaryExpr.Opcode.Or;
+ } else if (opCode == BinaryExpr.Opcode.Or) {
+ return BinaryExpr.Opcode.And;
+ } else {
+ throw new ArgumentException();
+ }
+ }
+
+ // NOTE: If we wanted to split quantifiers as far as possible, it would be
+ // enough to put the formulas in DNF (for foralls) or CNF (for exists).
+ // Unfortunately, this would cause ill-behaved quantifiers to produce
+ // exponentially many smaller quantifiers. Thus we only do one step of
+ // distributing, which takes care of the usual precondition case:
+ // forall x :: P(x) ==> (Q(x) && R(x))
+
+ private static UnaryOpExpr Not(Expression expr) {
+ var not = new UnaryOpExpr(expr.tok, UnaryOpExpr.Opcode.Not, expr) { Type = expr.Type };
+ return not;
+ }
+
+ internal static IEnumerable<Expression> SplitExpr(Expression expr, BinaryExpr.Opcode separator) {
+ expr = expr.Resolved;
+ var unary = expr as UnaryOpExpr;
+ var binary = expr as BinaryExpr;
+
+ if (unary != null && unary.Op == UnaryOpExpr.Opcode.Not) {
+ foreach (var e in SplitExpr(unary.E, FlipOpcode(separator))) { yield return Not(e); }
+ } else if (binary != null && binary.Op == separator) {
+ foreach (var e in SplitExpr(binary.E0, separator)) { yield return e; }
+ foreach (var e in SplitExpr(binary.E1, separator)) { yield return e; }
+ } else if (binary != null && binary.Op == BinaryExpr.Opcode.Imp && separator == BinaryExpr.Opcode.Or) {
+ foreach (var e in SplitExpr(Not(binary.E0), separator)) { yield return e; }
+ foreach (var e in SplitExpr(binary.E1, separator)) { yield return e; }
+ } else {
+ yield return expr;
+ }
+ }
+
+ internal static IEnumerable<Expression> SplitAndStich(BinaryExpr pair, BinaryExpr.Opcode separator) {
+ foreach (var e1 in SplitExpr(pair.E1, separator)) {
+ yield return new BinaryExpr(pair.tok, pair.Op, pair.E0, e1) { ResolvedOp = pair.ResolvedOp, Type = pair.Type };
+ }
+ }
+
+ internal static IEnumerable<Expression> SplitQuantifier(QuantifierExpr quantifier) {
+ var body = quantifier.Term;
+ var binary = body as BinaryExpr;
+
+ if (quantifier is ForallExpr) {
+ IEnumerable<Expression> stream;
+ if (binary != null && (binary.Op == BinaryExpr.Opcode.Imp || binary.Op == BinaryExpr.Opcode.Or)) {
+ stream = SplitAndStich(binary, BinaryExpr.Opcode.And);
+ } else {
+ stream = SplitExpr(body, BinaryExpr.Opcode.And);
+ }
+ foreach (var e in stream) {
+ var tok = new NestedToken(quantifier.tok, e.tok);
+ yield return new ForallExpr(tok, quantifier.TypeArgs, quantifier.BoundVars, quantifier.Range, e, quantifier.Attributes) { Type = quantifier.Type };
+ }
+ } else if (quantifier is ExistsExpr) {
+ IEnumerable<Expression> stream;
+ if (binary != null && binary.Op == BinaryExpr.Opcode.And) {
+ stream = SplitAndStich(binary, BinaryExpr.Opcode.Or);
+ } else {
+ stream = SplitExpr(body, BinaryExpr.Opcode.Or);
+ }
+ foreach (var e in stream) {
+ var tok = new NestedToken(quantifier.tok, e.tok);
+ yield return new ExistsExpr(tok, quantifier.TypeArgs, quantifier.BoundVars, quantifier.Range, e, quantifier.Attributes) { Type = quantifier.Type };
+ }
+ } else {
+ yield return quantifier;
+ }
+ }
+
+ protected override void VisitOneExpr(Expression expr) {
+ var quantifier = expr as QuantifierExpr;
+ if (quantifier != null) {
+ var split = SplitQuantifier(quantifier).ToList();
+ quantifier.SplitQuantifier = split;
+ //Console.WriteLine("!!! {0} => {1}", Printer.ExprToString(expr), rew.MapConcat(Printer.ExprToString, " ||| "));
+ }
+ }
+ }
+}
diff --git a/Source/Dafny/Triggers/QuantifiersCollection.cs b/Source/Dafny/Triggers/QuantifiersCollection.cs new file mode 100644 index 00000000..a6340f10 --- /dev/null +++ b/Source/Dafny/Triggers/QuantifiersCollection.cs @@ -0,0 +1,197 @@ +#define QUANTIFIER_WARNINGS
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Microsoft.Boogie;
+using System.Diagnostics.Contracts;
+
+//FIXME Generated triggers should be _triggers
+//FIXME: When scoring, do not consider old(x) to be higher than x.
+
+namespace Microsoft.Dafny.Triggers {
+ class QuantifierWithTriggers {
+ internal QuantifierExpr quantifier;
+ internal List<TriggerTerm> CandidateTerms;
+ internal List<TriggerCandidate> Candidates;
+ internal List<TriggerCandidate> RejectedCandidates;
+
+ internal bool AllowsLoops { get { return TriggerUtils.AllowsMatchingLoops(quantifier); } }
+ internal bool CouldSuppressLoops { get; set; }
+
+ internal QuantifierWithTriggers(QuantifierExpr quantifier) {
+ this.quantifier = quantifier;
+ this.RejectedCandidates = new List<TriggerCandidate>();
+ }
+
+ internal void TrimInvalidTriggers() {
+ Contract.Requires(CandidateTerms != null);
+ Contract.Requires(Candidates != null);
+ Candidates = TriggerUtils.Filter(Candidates, tr => tr.MentionsAll(quantifier.BoundVars), tr => { }).ToList();
+ }
+ }
+
+ class QuantifiersCollection {
+ readonly ErrorReporter reporter;
+ readonly List<QuantifierWithTriggers> quantifiers;
+
+ internal QuantifiersCollection(IEnumerable<QuantifierExpr> quantifiers, ErrorReporter reporter) {
+ this.reporter = reporter;
+ this.quantifiers = quantifiers.Select(q => new QuantifierWithTriggers(q)).ToList();
+ }
+
+ internal void ComputeTriggers(TriggersCollector triggersCollector) {
+ CollectAndShareTriggers(triggersCollector);
+ TrimInvalidTriggers();
+ BuildDependenciesGraph();
+ SuppressMatchingLoops();
+ SelectTriggers();
+ }
+
+ private bool SubsetGenerationPredicate(List<TriggerTerm> terms, TriggerTerm additionalTerm) {
+ // Simple formulas like [P0(i) && P1(i) && P2(i) && P3(i) && P4(i)] yield very
+ // large numbers of multi-triggers, most of which are useless. This filter
+ // restricts subsets of terms so that we only generate sets of terms where each
+ // element contributes at least one variable. In the example above, we'll only
+ // get 5 triggers.
+ // Note that this may still be an over-approximation, as in the following example:
+ // forall a, b :: forall x :: a[x] || b[x] > 0.
+ return additionalTerm.Variables.Where(v => v is BoundVar && !terms.Any(t => t.Variables.Contains(v))).Any();
+ }
+
+ //FIXME document that this assumes that the quantifiers live in the same context and share the same variables
+ void CollectAndShareTriggers(TriggersCollector triggersCollector) {
+ var pool = quantifiers.SelectMany(q => triggersCollector.CollectTriggers(q.quantifier));
+ var distinctPool = pool.Deduplicate(TriggerTerm.Eq);
+ var multiPool = TriggerUtils.AllNonEmptySubsets(distinctPool, SubsetGenerationPredicate).Select(candidates => new TriggerCandidate(candidates)).ToList();
+
+ foreach (var q in quantifiers) {
+ q.CandidateTerms = distinctPool; //Candidate terms are immutable: no copy needed
+ q.Candidates = multiPool.Select(candidate => new TriggerCandidate(candidate)).ToList();
+ }
+ }
+
+ private void TrimInvalidTriggers() {
+ foreach (var q in quantifiers) {
+ q.TrimInvalidTriggers();
+ }
+ }
+
+ void BuildDependenciesGraph() {
+ // FIXME: Think more about multi-quantifier dependencies
+ //class QuantifierDependency {
+ // QuantifierWithTriggers Cause;
+ // QuantifierWithTriggers Consequence;
+ // List<TriggerCandidate> Triggers;
+ // List<Expression> MatchingTerm;
+ //}
+ }
+
+ void SuppressMatchingLoops() {
+ // NOTE: This only looks for self-loops; that is, loops involving a single
+ // quantifier.
+
+ // For a given quantifier q, we introduce a triggering relation between trigger
+ // candidates by writing t1 → t2 if instantiating q from t1 introduces a ground
+ // term that matches t2. Then, we notice that this relation is transitive, since
+ // all triggers yield the same set of terms. This means that any matching loop
+ // t1 → ... → t1 can be reduced to a self-loop t1 → t1. Detecting such
+ // self-loops is then only a matter of finding terms in the body of the
+ // quantifier that match a given trigger.
+
+ // Of course, each trigger that actually appears in the body of the quantifier
+ // yields a trivial self-loop (e.g. P(i) in [∀ i {P(i)} ⋅ P(i)]), so we
+ // ignore this type of loops. In fact, we ignore any term in the body of the
+ // quantifier that matches one of the terms of the trigger (this ensures that
+ // [∀ x {f(x), f(f(x))} ⋅ f(x) = f(f(x))] is not a loop). And we even
+ // ignore terms that almost match a trigger term, modulo a single variable
+ // (this ensures that [∀ x y {a(x, y)} ⋅ a(x, y) == a(y, x)] is not a loop).
+ // This ignoring logic is implemented by the CouldCauseLoops method.
+
+ foreach (var q in quantifiers) {
+ var looping = new List<TriggerCandidate>();
+ var loopingSubterms = q.Candidates.ToDictionary(candidate => candidate, candidate => candidate.LoopingSubterms(q.quantifier).ToList());
+
+ var safe = TriggerUtils.Filter(
+ q.Candidates,
+ c => !loopingSubterms[c].Any(),
+ c => {
+ looping.Add(c);
+ c.Annotation = "loops with " + loopingSubterms[c].MapConcat(t => Printer.ExprToString(t.Expr), ", ");
+ }).ToList();
+
+ q.CouldSuppressLoops = safe.Count > 0;
+
+ if (!q.AllowsLoops && q.CouldSuppressLoops) {
+ q.Candidates = safe;
+ q.RejectedCandidates.AddRange(looping);
+ }
+ }
+ }
+
+ void SelectTriggers() {
+ //FIXME
+ }
+
+ private void CommitOne(QuantifierWithTriggers q, bool addHeader) {
+ var errorLevel = ErrorLevel.Info;
+ var msg = new StringBuilder();
+ var indent = addHeader ? " " : " "; //FIXME if multiline messages were properly supported, this indentation wouldn't be needed
+
+ if (!TriggerUtils.NeedsAutoTriggers(q.quantifier)) { //FIXME: matchingloop and autotriggers attributes are passed down to Boogie
+ msg.AppendFormat("Not generating triggers for {{{0}}}.", Printer.ExprToString(q.quantifier.Term)).AppendLine();
+ // FIXME This shouldn't be printed for autoReqs. (see autoReq.dfy)
+ // FIXME typeQuantifier?
+ } else {
+ if (addHeader) {
+ msg.AppendFormat("For expression {{{0}}}:", Printer.ExprToString(q.quantifier.Term)).AppendLine();
+ }
+
+ foreach (var candidate in q.Candidates) { //FIXME make this _trigger instead of trigger
+ q.quantifier.Attributes = new Attributes("trigger", candidate.Terms.Select(t => t.Expr).ToList(), q.quantifier.Attributes);
+ }
+
+ AddTriggersToMessage("Selected triggers:", q.Candidates, msg, indent);
+ AddTriggersToMessage("Rejected triggers:", q.RejectedCandidates, msg, indent, true);
+
+#if QUANTIFIER_WARNINGS
+ string WARN = (msg.Length > 0 ? indent : "") + (DafnyOptions.O.UnicodeOutput ? "⚠ " : "(!) ");
+ if (!q.CandidateTerms.Any()) {
+ errorLevel = ErrorLevel.Warning;
+ msg.Append(WARN).AppendLine("No terms found to trigger on.");
+ } else if (!q.Candidates.Any()) {
+ errorLevel = ErrorLevel.Warning;
+ msg.Append(WARN).AppendLine("No trigger covering all quantified variables found.");
+ } else if (!q.CouldSuppressLoops && !q.AllowsLoops) {
+ errorLevel = ErrorLevel.Warning;
+ msg.Append(WARN).AppendLine("Suppressing loops would leave this expression without triggers.");
+ }
+#endif
+ }
+
+ if (msg.Length > 0) {
+ reporter.Message(MessageSource.Rewriter, errorLevel, q.quantifier.tok, msg.ToString().TrimEnd("\r\n".ToCharArray()));
+ }
+ }
+
+ private static void AddTriggersToMessage<T>(string header, List<T> triggers, StringBuilder msg, string indent, bool newlines = false) {
+ if (triggers.Any()) {
+ msg.Append(indent).Append(header);
+ if (triggers.Count == 1) {
+ msg.Append(" ");
+ } else if (triggers.Count > 1) {
+ msg.AppendLine().Append(indent).Append(" ");
+ }
+ var separator = newlines && triggers.Count > 1 ? Environment.NewLine + indent + " " : ", ";
+ msg.AppendLine(String.Join(separator, triggers));
+ }
+ }
+
+ internal void CommitTriggers() {
+ foreach (var q in quantifiers) {
+ CommitOne(q, quantifiers.Count > 1);
+ }
+ }
+ }
+}
diff --git a/Source/Dafny/Triggers/QuantifiersCollector.cs b/Source/Dafny/Triggers/QuantifiersCollector.cs new file mode 100644 index 00000000..b30cb6b1 --- /dev/null +++ b/Source/Dafny/Triggers/QuantifiersCollector.cs @@ -0,0 +1,37 @@ +using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Microsoft.Boogie;
+using System.Collections.ObjectModel;
+using System.Diagnostics.Contracts;
+
+namespace Microsoft.Dafny.Triggers { //FIXME rename this file
+ internal class QuantifierCollector : TopDownVisitor<object> {
+ readonly ErrorReporter reporter;
+ private HashSet<Expression> quantifiers = new HashSet<Expression>();
+ internal List<QuantifiersCollection> quantifierCollections = new List<QuantifiersCollection>();
+
+ public QuantifierCollector(ErrorReporter reporter) {
+ Contract.Requires(reporter != null);
+ this.reporter = reporter;
+ }
+
+ protected override bool VisitOneExpr(Expression expr, ref object _) {
+ var quantifier = expr as QuantifierExpr;
+
+ if (quantifier != null && !quantifiers.Contains(quantifier)) {
+ quantifiers.Add(quantifier);
+ if (quantifier.SplitQuantifier != null) {
+ var collection = quantifier.SplitQuantifier.Select(q => q as QuantifierExpr).Where(q => q != null);
+ quantifierCollections.Add(new QuantifiersCollection(collection, reporter));
+ foreach (var q in quantifier.SplitQuantifier) { quantifiers.Add(q); }
+ } else {
+ quantifierCollections.Add(new QuantifiersCollection(Enumerable.Repeat(quantifier, 1), reporter));
+ }
+ }
+
+ return true;
+ }
+ }
+}
diff --git a/Source/Dafny/Triggers/TriggerExtensions.cs b/Source/Dafny/Triggers/TriggerExtensions.cs new file mode 100644 index 00000000..a49ed13a --- /dev/null +++ b/Source/Dafny/Triggers/TriggerExtensions.cs @@ -0,0 +1,495 @@ +#define THROW_UNSUPPORTED_COMPARISONS
+
+using Microsoft.Dafny;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics.Contracts;
+using System.Linq;
+using System.Text;
+
+namespace Microsoft.Dafny.Triggers {
+ internal static class DeduplicateExtension {
+ public static List<T> Deduplicate<T>(this IEnumerable<T> seq, Func<T, T, bool> eq) {
+ List<T> deduplicated = new List<T>();
+
+ foreach (var elem in seq) {
+ if (!deduplicated.Any(other => eq(elem, other))) {
+ deduplicated.Add(elem);
+ }
+ }
+
+ return deduplicated;
+ }
+ }
+
+ internal struct TriggerMatch {
+ internal Expression Expr;
+ internal Dictionary<IVariable, Expression> Bindings;
+
+ internal static bool Eq(TriggerMatch t1, TriggerMatch t2) {
+ return ExprExtensions.ExpressionEq(t1.Expr, t2.Expr);
+ }
+
+ internal bool CouldCauseLoops(List<TriggerTerm> terms) {
+ var expr = Expr;
+ return !terms.Any(term => term.Expr.ExpressionEqModuloVariableNames(expr));
+ }
+ }
+
+ internal static class ExprExtensions {
+ internal static IEnumerable<Expression> AllSubExpressions(this Expression expr, bool strict = false) {
+ foreach (var subexpr in expr.SubExpressions) {
+ foreach (var r_subexpr in AllSubExpressions(subexpr, false)) {
+ yield return r_subexpr;
+ }
+ yield return subexpr;
+ }
+
+ if (expr is StmtExpr) {
+ foreach (var r_subexpr in AllSubExpressions(((StmtExpr)expr).S, false)) {
+ yield return r_subexpr;
+ }
+ }
+
+ if (!strict) {
+ yield return expr;
+ }
+ }
+
+ internal static IEnumerable<Expression> AllSubExpressions(this Statement stmt, bool strict = false) {
+ foreach (var subexpr in stmt.SubExpressions) {
+ foreach (var r_subexpr in AllSubExpressions(subexpr, false)) {
+ yield return r_subexpr;
+ }
+ yield return subexpr;
+ }
+
+ foreach (var substmt in stmt.SubStatements) {
+ foreach (var r_subexpr in AllSubExpressions(substmt, false)) {
+ yield return r_subexpr;
+ }
+ }
+ }
+
+ internal static bool ExpressionEq(this Expression expr1, Expression expr2) {
+ expr1 = expr1.Resolved;
+ expr2 = expr2.Resolved;
+
+ return ShallowEq_Top(expr1, expr2) && TriggerUtils.SameLists(expr1.SubExpressions, expr2.SubExpressions, (e1, e2) => ExpressionEq(e1, e2));
+ }
+
+ internal static bool ExpressionEqModuloVariableNames(this Expression expr1, Expression expr2) {
+ expr1 = expr1.Resolved;
+ expr2 = expr2.Resolved;
+
+ if (expr1 is IdentifierExpr) {
+ return expr2 is IdentifierExpr;
+ }
+
+ return ShallowEq_Top(expr1, expr2) && TriggerUtils.SameLists(expr1.SubExpressions, expr2.SubExpressions, (e1, e2) => ExpressionEqModuloVariableNames(e1, e2));
+ }
+
+ internal static bool MatchesTrigger(this Expression expr, Expression trigger, ISet<BoundVar> holes, Dictionary<IVariable, Expression> bindings) {
+ expr = expr.Resolved;
+ trigger = trigger.Resolved;
+
+ if (trigger is IdentifierExpr) {
+ var var = ((IdentifierExpr)trigger).Var;
+
+ if (holes.Contains(var)) {
+ Expression existing_binding = null;
+ if (bindings.TryGetValue(var, out existing_binding)) {
+ return ExpressionEq(expr, existing_binding);
+ } else {
+ bindings[var] = expr;
+ return true;
+ }
+ }
+ }
+
+ return ShallowEq_Top(expr, trigger) && TriggerUtils.SameLists(expr.SubExpressions, trigger.SubExpressions, (e1, e2) => MatchesTrigger(e1, e2, holes, bindings));
+ }
+
+ private static TriggerMatch? MatchAgainst(this Expression expr, Expression trigger, IEnumerable<BoundVar> holes) {
+ var bindings = new Dictionary<IVariable, Expression>();
+ if (expr.MatchesTrigger(trigger, new HashSet<BoundVar>(holes), bindings)) {
+ return new TriggerMatch { Expr = expr, Bindings = bindings };
+ } else {
+ return null;
+ }
+ }
+
+ internal static IEnumerable<TriggerMatch> SubexpressionsMatchingTrigger(this QuantifierExpr quantifier, Expression trigger) {
+ return quantifier.Term.AllSubExpressions()
+ .Select(e => TriggerUtils.CleanupExprForInclusionInTrigger(e).MatchAgainst(trigger, quantifier.BoundVars))
+ .Where(e => e.HasValue).Select(e => e.Value);
+ }
+
+ private static bool ShallowSameAttributes(Attributes attributes1, Attributes attributes2) {
+ return TriggerUtils.SameLists(attributes1.AsEnumerable(), attributes2.AsEnumerable(), ShallowSameSingleAttribute);
+ }
+
+ private static bool ShallowSameSingleAttribute(Attributes arg1, Attributes arg2) {
+ return arg1.Name == arg2.Name;
+ }
+
+ private static bool SameBoundVar(IVariable arg1, IVariable arg2) {
+ return arg1 == arg2 ||
+ (arg1.Name == arg2.Name &&
+ arg1.CompileName == arg2.CompileName &&
+ arg1.DisplayName == arg2.DisplayName &&
+ arg1.UniqueName == arg2.UniqueName &&
+ arg1.IsGhost == arg2.IsGhost &&
+ arg1.IsMutable == arg2.IsMutable &&
+ ((arg1.Type == null && arg2.Type == null) || arg1.Type.Equals(arg2.Type)));
+ }
+
+ /// <summary>
+ /// Compares two abstract syntax expressions, looking only at their direct members. Subexpressions and substatements are not compared.
+ /// </summary>
+ /// <returns></returns>
+ internal static bool ShallowEq_Top(Expression expr1, Expression expr2) {
+ Contract.Requires(expr1 != null);
+ Contract.Requires(expr2 != null);
+
+ // We never compare concrete expressions
+ Contract.Requires(!(expr1 is ConcreteSyntaxExpression));
+ Contract.Requires(!(expr2 is ConcreteSyntaxExpression));
+
+ // CPC: Hey future editor: the following block of code is auto-generated. Just add your own cases at the end.
+ // This could be a visitor pattern, except I need to visit a pair of nodes.
+ // It could also be implemented in each individual class. I'd have a slight preference for that.
+ // This really just wants to use double dispatch.
+ if (expr1 is UnboxingCastExpr && expr2 is UnboxingCastExpr) {
+ return ShallowEq((UnboxingCastExpr)expr1, (UnboxingCastExpr)expr2);
+ } else if (expr1 is BoxingCastExpr && expr2 is BoxingCastExpr) {
+ return ShallowEq((BoxingCastExpr)expr1, (BoxingCastExpr)expr2);
+ } else if (expr1 is MatchExpr && expr2 is MatchExpr) {
+ return ShallowEq((MatchExpr)expr1, (MatchExpr)expr2);
+ } else if (expr1 is ITEExpr && expr2 is ITEExpr) {
+ return ShallowEq((ITEExpr)expr1, (ITEExpr)expr2);
+ } else if (expr1 is StmtExpr && expr2 is StmtExpr) {
+ return ShallowEq((StmtExpr)expr1, (StmtExpr)expr2);
+ } else if (expr1 is WildcardExpr && expr2 is WildcardExpr) {
+ return ShallowEq((WildcardExpr)expr1, (WildcardExpr)expr2);
+ } else if (expr1 is ComprehensionExpr && expr2 is ComprehensionExpr) {
+ return ShallowEq((ComprehensionExpr)expr1, (ComprehensionExpr)expr2);
+ } else if (expr1 is NamedExpr && expr2 is NamedExpr) {
+ return ShallowEq((NamedExpr)expr1, (NamedExpr)expr2);
+ } else if (expr1 is LetExpr && expr2 is LetExpr) {
+ return ShallowEq((LetExpr)expr1, (LetExpr)expr2);
+ } else if (expr1 is TernaryExpr && expr2 is TernaryExpr) {
+ return ShallowEq((TernaryExpr)expr1, (TernaryExpr)expr2);
+ } else if (expr1 is BinaryExpr && expr2 is BinaryExpr) {
+ return ShallowEq((BinaryExpr)expr1, (BinaryExpr)expr2);
+ } else if (expr1 is UnaryExpr && expr2 is UnaryExpr) {
+ return ShallowEq((UnaryExpr)expr1, (UnaryExpr)expr2);
+ } else if (expr1 is MultiSetFormingExpr && expr2 is MultiSetFormingExpr) {
+ return ShallowEq((MultiSetFormingExpr)expr1, (MultiSetFormingExpr)expr2);
+ } else if (expr1 is OldExpr && expr2 is OldExpr) {
+ return ShallowEq((OldExpr)expr1, (OldExpr)expr2);
+ } else if (expr1 is FunctionCallExpr && expr2 is FunctionCallExpr) {
+ return ShallowEq((FunctionCallExpr)expr1, (FunctionCallExpr)expr2);
+ } else if (expr1 is ApplyExpr && expr2 is ApplyExpr) {
+ return ShallowEq((ApplyExpr)expr1, (ApplyExpr)expr2);
+ } else if (expr1 is SeqUpdateExpr && expr2 is SeqUpdateExpr) {
+ return ShallowEq((SeqUpdateExpr)expr1, (SeqUpdateExpr)expr2);
+ } else if (expr1 is MultiSelectExpr && expr2 is MultiSelectExpr) {
+ return ShallowEq((MultiSelectExpr)expr1, (MultiSelectExpr)expr2);
+ } else if (expr1 is SeqSelectExpr && expr2 is SeqSelectExpr) {
+ return ShallowEq((SeqSelectExpr)expr1, (SeqSelectExpr)expr2);
+ } else if (expr1 is MemberSelectExpr && expr2 is MemberSelectExpr) {
+ return ShallowEq((MemberSelectExpr)expr1, (MemberSelectExpr)expr2);
+ } else if (expr1 is MapDisplayExpr && expr2 is MapDisplayExpr) { //Note: MapDisplayExpr is not a DisplayExpression
+ return ShallowEq((MapDisplayExpr)expr1, (MapDisplayExpr)expr2);
+ } else if (expr1 is DisplayExpression && expr2 is DisplayExpression) {
+ return ShallowEq((DisplayExpression)expr1, (DisplayExpression)expr2);
+ } else if (expr1 is IdentifierExpr && expr2 is IdentifierExpr) {
+ return ShallowEq((IdentifierExpr)expr1, (IdentifierExpr)expr2);
+ } else if (expr1 is ThisExpr && expr2 is ThisExpr) {
+ return ShallowEq((ThisExpr)expr1, (ThisExpr)expr2);
+ } else if (expr1 is DatatypeValue && expr2 is DatatypeValue) {
+ return ShallowEq((DatatypeValue)expr1, (DatatypeValue)expr2);
+ } else if (expr1 is LiteralExpr && expr2 is LiteralExpr) {
+ return ShallowEq((LiteralExpr)expr1, (LiteralExpr)expr2);
+ } else {
+ // If this assertion fail, then a new abstract AST node was probably introduced but not registered here.
+ Contract.Assert(expr1.GetType() != expr2.GetType());
+ return false;
+ }
+ }
+
+ private static bool ShallowEq(UnboxingCastExpr expr1, UnboxingCastExpr expr2) {
+ Contract.Requires(false);
+ throw new InvalidOperationException();
+ }
+
+ private static bool ShallowEq(BoxingCastExpr expr1, BoxingCastExpr expr2) {
+ return expr1.FromType == expr2.FromType &&
+ expr1.ToType == expr2.ToType;
+ }
+
+ private static bool ShallowEq(MatchExpr expr1, MatchExpr expr2) {
+ return true;
+ }
+
+ private static bool ShallowEq(ITEExpr expr1, ITEExpr expr2) {
+ return true;
+ }
+
+ private static bool ShallowEq(StmtExpr expr1, StmtExpr expr2) {
+#if THROW_UNSUPPORTED_COMPARISONS
+ Contract.Assume(false); // This kind of expression never appears in a trigger
+ throw new NotImplementedException();
+#else
+ return expr1.S == expr2.S;
+#endif
+ }
+
+ private static bool ShallowEq(WildcardExpr expr1, WildcardExpr expr2) {
+ return true;
+ }
+
+ private static bool ShallowEq(LambdaExpr expr1, LambdaExpr expr2) {
+#if THROW_UNSUPPORTED_COMPARISONS
+ Contract.Assume(false); // This kind of expression never appears in a trigger
+ throw new NotImplementedException();
+#else
+ return false;
+#endif
+ }
+
+ private static bool ShallowEq(MapComprehension expr1, MapComprehension expr2) {
+ return expr1.Finite == expr2.Finite;
+ }
+
+ private static bool ShallowEq(SetComprehension expr1, SetComprehension expr2) {
+ return expr1.TermIsImplicit == expr2.TermIsImplicit && //TODO
+ expr1.Finite == expr2.Finite;
+ }
+
+ private static bool ShallowEq(ExistsExpr expr1, ExistsExpr expr2) {
+ return true;
+ }
+
+ private static bool ShallowEq(ForallExpr expr1, ForallExpr expr2) {
+ return true;
+ }
+
+ private static bool ShallowEq(QuantifierExpr expr1, QuantifierExpr expr2) {
+ if (!TriggerUtils.SameNullity(expr1.SplitQuantifier, expr2.SplitQuantifier)) {
+ return false;
+ }
+
+ if (expr1.SplitQuantifier != null && expr2.SplitQuantifier != null) {
+ return ShallowEq_Top(expr1.SplitQuantifierExpression, expr2.SplitQuantifierExpression);
+ }
+
+ if (expr1.TypeArgs.Count != expr2.TypeArgs.Count ||
+ !TriggerUtils.SameNullity(expr1.Range, expr2.Range)) {
+ return false;
+ }
+
+ if (expr1 is ExistsExpr && expr2 is ExistsExpr) {
+ return ShallowEq((ExistsExpr)expr1, (ExistsExpr)expr2);
+ } else if (expr1 is ForallExpr && expr2 is ForallExpr) {
+ return ShallowEq((ForallExpr)expr1, (ForallExpr)expr2);
+ } else {
+ return false;
+ }
+ }
+
+ private static bool ShallowEq(ComprehensionExpr expr1, ComprehensionExpr expr2) {
+ if (!TriggerUtils.SameLists(expr1.BoundVars, expr2.BoundVars, SameBoundVar) ||
+ !ShallowSameAttributes(expr1.Attributes, expr2.Attributes) ||
+ // Filled in during resolution: !SameLists(expr1.Bounds, expr2.Bounds, ReferenceCompare) ||
+ // !SameLists(expr1.MissingBounds, expr2.MissingBounds, SameBoundVar) ||
+ !TriggerUtils.SameNullity(expr1.Range, expr2.Range)) { //TODO Check
+ return false;
+ }
+
+ if (expr1 is LambdaExpr && expr2 is LambdaExpr) {
+ return ShallowEq((LambdaExpr)expr1, (LambdaExpr)expr2);
+ } else if (expr1 is MapComprehension && expr2 is MapComprehension) {
+ return ShallowEq((MapComprehension)expr1, (MapComprehension)expr2);
+ } else if (expr1 is SetComprehension && expr2 is SetComprehension) {
+ return ShallowEq((SetComprehension)expr1, (SetComprehension)expr2);
+ } else if (expr1 is QuantifierExpr && expr2 is QuantifierExpr) {
+ return ShallowEq((QuantifierExpr)expr1, (QuantifierExpr)expr2);
+ } else {
+ return false; // ComprehensionExpr is abstract
+ }
+ }
+
+ private static bool ShallowEq(NamedExpr expr1, NamedExpr expr2) {
+ return expr1.Name == expr2.Name &&
+ TriggerUtils.SameNullity(expr1.Contract, expr2.Contract);
+ }
+
+ private static bool ShallowEq(LetExpr expr1, LetExpr expr2) {
+ return expr1.Exact == expr2.Exact &&
+ ShallowSameAttributes(expr1.Attributes, expr2.Attributes);
+ }
+
+ private static bool ShallowEq(TernaryExpr expr1, TernaryExpr expr2) {
+ return expr1.Op == expr2.Op;
+ }
+
+ private static bool ShallowEq(BinaryExpr expr1, BinaryExpr expr2) {
+ Contract.Requires(expr1.ResolvedOp != BinaryExpr.ResolvedOpcode.YetUndetermined);
+ Contract.Requires(expr2.ResolvedOp != BinaryExpr.ResolvedOpcode.YetUndetermined);
+ return expr1.ResolvedOp == expr2.ResolvedOp;
+ }
+
+ private static bool ShallowEq(ConversionExpr expr1, ConversionExpr expr2) {
+ return expr1.Type == expr2.Type; //TODO equality on types?
+ }
+
+ private static bool ShallowEq(UnaryOpExpr expr1, UnaryOpExpr expr2) {
+ return expr1.Op == expr2.Op;
+ }
+
+ private static bool ShallowEq(UnaryExpr expr1, UnaryExpr expr2) {
+ if (expr1 is ConversionExpr && expr2 is ConversionExpr) {
+ return ShallowEq((ConversionExpr)expr1, (ConversionExpr)expr2);
+ } else if (expr1 is UnaryOpExpr && expr2 is UnaryOpExpr) {
+ return ShallowEq((UnaryOpExpr)expr1, (UnaryOpExpr)expr2);
+ } else {
+ return false; // UnaryExpr is abstract
+ }
+ }
+
+ private static bool ShallowEq(MultiSetFormingExpr expr1, MultiSetFormingExpr expr2) {
+ return true;
+ }
+
+ private static bool ShallowEq(OldExpr expr1, OldExpr expr2) {
+ return true;
+ }
+
+ private static bool ShallowEq(FunctionCallExpr expr1, FunctionCallExpr expr2) {
+ return expr1.Name == expr2.Name &&
+ expr1.CoCall == expr2.CoCall && //TODO
+ expr1.Function == expr2.Function; // TODO TypeArgumentSubstitutions?
+ }
+
+ private static bool ShallowEq(ApplyExpr expr1, ApplyExpr expr2) {
+ return true;
+ }
+
+ private static bool ShallowEq(SeqUpdateExpr expr1, SeqUpdateExpr expr2) {
+ Contract.Requires(expr1.ResolvedUpdateExpr != null && expr2.ResolvedUpdateExpr != null);
+ return true;
+ }
+
+ private static bool ShallowEq(MultiSelectExpr expr1, MultiSelectExpr expr2) {
+ return true;
+ }
+
+ private static bool ShallowEq(SeqSelectExpr expr1, SeqSelectExpr expr2) {
+ return expr1.SelectOne == expr2.SelectOne &&
+ TriggerUtils.SameNullity(expr1.Seq, expr2.Seq) &&
+ TriggerUtils.SameNullity(expr1.E0, expr2.E0) &&
+ TriggerUtils.SameNullity(expr1.E1, expr2.E1);
+ }
+
+ private static bool ShallowEq(MemberSelectExpr expr1, MemberSelectExpr expr2) {
+ return expr1.MemberName == expr2.MemberName &&
+ expr1.Member == expr2.Member &&
+ TriggerUtils.SameLists(expr1.TypeApplication, expr2.TypeApplication, Microsoft.Dafny.Type.Equals);
+ }
+
+ private static bool ShallowEq(SeqDisplayExpr expr1, SeqDisplayExpr expr2) {
+ return true;
+ }
+
+ private static bool ShallowEq(MapDisplayExpr expr1, MapDisplayExpr expr2) {
+ return expr1.Finite == expr2.Finite;
+ }
+
+ private static bool ShallowEq(MultiSetDisplayExpr expr1, MultiSetDisplayExpr expr2) {
+ return true;
+ }
+
+ private static bool ShallowEq(SetDisplayExpr expr1, SetDisplayExpr expr2) {
+ return expr1.Finite == expr2.Finite;
+ }
+
+ private static bool ShallowEq(DisplayExpression expr1, DisplayExpression expr2) {
+ if (expr1 is SeqDisplayExpr && expr2 is SeqDisplayExpr) {
+ return ShallowEq((SeqDisplayExpr)expr1, (SeqDisplayExpr)expr2);
+ } else if (expr1 is MultiSetDisplayExpr && expr2 is MultiSetDisplayExpr) {
+ return ShallowEq((MultiSetDisplayExpr)expr1, (MultiSetDisplayExpr)expr2);
+ } else if (expr1 is SetDisplayExpr && expr2 is SetDisplayExpr) {
+ return ShallowEq((SetDisplayExpr)expr1, (SetDisplayExpr)expr2);
+ } else {
+ return false;
+ }
+ }
+
+ private static bool ShallowEq(AutoGhostIdentifierExpr expr1, AutoGhostIdentifierExpr expr2) {
+ return true;
+ }
+
+ private static bool ShallowEq(IdentifierExpr expr1, IdentifierExpr expr2) {
+ if (expr1.Name != expr2.Name ||
+ expr1.Var != expr2.Var) {
+ return false;
+ }
+
+ if (expr1 is AutoGhostIdentifierExpr && expr2 is AutoGhostIdentifierExpr) {
+ return ShallowEq((AutoGhostIdentifierExpr)expr1, (AutoGhostIdentifierExpr)expr2);
+ } else {
+ return true;
+ }
+ }
+
+ private static bool ShallowEq(ImplicitThisExpr expr1, ImplicitThisExpr expr2) {
+ return true;
+ }
+
+ private static bool ShallowEq(ThisExpr expr1, ThisExpr expr2) {
+ if (expr1 is ImplicitThisExpr && expr2 is ImplicitThisExpr) {
+ return ShallowEq((ImplicitThisExpr)expr1, (ImplicitThisExpr)expr2);
+ } else {
+ return (expr1.GetType() == expr2.GetType()); // LiteralExpr is not abstract
+ }
+ }
+
+ private static bool ShallowEq(DatatypeValue expr1, DatatypeValue expr2) {
+ return // Implied by Ctor equality: expr1.DatatypeName == expr2.DatatypeName &&
+ // Implied by Ctor equality: expr1.MemberName == expr2.MemberName &&
+ expr1.Ctor == expr2.Ctor &&
+ // Contextual information: expr1.IsCoCall == expr2.IsCoCall &&
+ TriggerUtils.SameLists(expr1.InferredTypeArgs, expr2.InferredTypeArgs, Microsoft.Dafny.Type.Equals);
+ }
+
+ private static bool ShallowEq(StringLiteralExpr expr1, StringLiteralExpr expr2) {
+ return true;
+ }
+
+ private static bool ShallowEq(CharLiteralExpr expr1, CharLiteralExpr expr2) {
+ return true;
+ }
+
+ private static bool ShallowEq(StaticReceiverExpr expr1, StaticReceiverExpr expr2) {
+ return true;
+ }
+
+ private static bool ShallowEq(LiteralExpr expr1, LiteralExpr expr2) {
+ if (!TriggerUtils.SameNullity(expr1.Value, expr2.Value) || (expr1.Value != null && !expr1.Value.Equals(expr2.Value))) {
+ return false;
+ }
+
+ if (expr1 is StringLiteralExpr && expr2 is StringLiteralExpr) {
+ return ShallowEq((StringLiteralExpr)expr1, (StringLiteralExpr)expr2);
+ } else if (expr1 is CharLiteralExpr && expr2 is CharLiteralExpr) {
+ return ShallowEq((CharLiteralExpr)expr1, (CharLiteralExpr)expr2);
+ } else if (expr1 is StaticReceiverExpr && expr2 is StaticReceiverExpr) {
+ return ShallowEq((StaticReceiverExpr)expr1, (StaticReceiverExpr)expr2);
+ } else {
+ return (expr1.GetType() == expr2.GetType()); // LiteralExpr is not abstract
+ }
+ }
+ }
+}
diff --git a/Source/Dafny/Triggers/TriggerUtils.cs b/Source/Dafny/Triggers/TriggerUtils.cs new file mode 100644 index 00000000..9ebcf846 --- /dev/null +++ b/Source/Dafny/Triggers/TriggerUtils.cs @@ -0,0 +1,162 @@ +#define DEBUG_AUTO_TRIGGERS
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Diagnostics.Contracts;
+using System.Linq;
+using System.Text;
+
+namespace Microsoft.Dafny.Triggers {
+ class TriggerUtils {
+ internal static List<T> CopyAndAdd<T>(List<T> seq, T elem) {
+ var copy = new List<T>(seq);
+ copy.Add(elem);
+ return copy;
+ }
+
+ internal static IEnumerable<List<T>> AllSubsets<T>(IList<T> source, Func<List<T>, T, bool> predicate, int offset) {
+ if (offset >= source.Count) {
+ yield return new List<T>();
+ yield break;
+ }
+
+ foreach (var subset in AllSubsets<T>(source, predicate, offset + 1)) {
+ if (predicate(subset, source[offset])) {
+ yield return CopyAndAdd(subset, source[offset]);
+ }
+ yield return new List<T>(subset);
+ }
+ }
+
+ internal static IEnumerable<List<T>> AllNonEmptySubsets<T>(IEnumerable<T> source, Func<List<T>, T, bool> predicate) {
+ List<T> all = new List<T>(source);
+ foreach (var subset in AllSubsets(all, predicate, 0)) {
+ if (subset.Count > 0) {
+ yield return subset;
+ }
+ }
+ }
+
+ internal static List<T> MergeAlterFirst<T>(List<T> a, List<T> b) {
+ Contract.Requires(a != null);
+ Contract.Requires(b != null);
+ a.AddRange(b);
+ return a;
+ }
+
+ internal static ISet<T> MergeAlterFirst<T>(ISet<T> a, ISet<T> b) {
+ Contract.Requires(a != null);
+ Contract.Requires(b != null);
+ a.UnionWith(b);
+ return a;
+ }
+
+ internal static bool SameLists<T>(IEnumerable<T> list1, IEnumerable<T> list2, Func<T, T, bool> comparer) {
+ if (ReferenceEquals(list1, list2)) {
+ return true;
+ } else if ((list1 == null) != (list2 == null)) {
+ return false;
+ }
+
+ var it1 = list1.GetEnumerator();
+ var it2 = list2.GetEnumerator();
+ bool it1_has, it2_has;
+ bool acc = true;
+
+ do {
+ it1_has = it1.MoveNext();
+ it2_has = it2.MoveNext();
+
+ if (it1_has == true && it2_has == true) {
+ acc = acc && comparer(it1.Current, it2.Current);
+ }
+ } while (it1_has && it2_has);
+
+ return it1_has == it2_has && acc;
+ }
+
+ internal static IEnumerable<T> Filter<T>(IEnumerable<T> elements, Func<T, bool> predicate, Action<T> reject) {
+ var positive = new List<T>();
+ foreach (var c in elements) {
+ if (predicate(c)) {
+ yield return c;
+ } else {
+ reject(c);
+ }
+ }
+ }
+
+ internal static bool SameNullity<T>(T x1, T x2) where T : class {
+ return (x1 == null) == (x2 == null);
+ }
+
+ internal string JoinStringsWithHeader(string header, IEnumerable<string> lines) {
+ return header + String.Join(Environment.NewLine + new String(' ', header.Length), lines);
+ }
+
+ [Conditional("DEBUG_AUTO_TRIGGERS")]
+ internal static void DebugTriggers(string format, params object[] more) {
+ Console.Error.WriteLine(format, more);
+ }
+
+ internal static bool AllowsMatchingLoops(QuantifierExpr quantifier) {
+ Contract.Requires(quantifier.SplitQuantifier == null); // Don't call this on a quantifier with a Split clause: it's not a real quantifier
+ return Attributes.Contains(quantifier.Attributes, "matchingloop");
+ }
+
+ internal static bool NeedsAutoTriggers(QuantifierExpr quantifier) {
+ Contract.Requires(quantifier.SplitQuantifier == null); // Don't call this on a quantifier with a Split clause: it's not a real quantifier
+ bool wantsAutoTriggers = true;
+ return !Attributes.Contains(quantifier.Attributes, "trigger") &&
+ (!Attributes.ContainsBool(quantifier.Attributes, "autotriggers", ref wantsAutoTriggers) || wantsAutoTriggers);
+ }
+
+ internal static BinaryExpr.ResolvedOpcode RemoveNotInBinaryExprIn(BinaryExpr.ResolvedOpcode opcode) {
+ switch (opcode) {
+ case BinaryExpr.ResolvedOpcode.NotInMap:
+ return BinaryExpr.ResolvedOpcode.InMap;
+ case BinaryExpr.ResolvedOpcode.NotInSet:
+ return BinaryExpr.ResolvedOpcode.InSet;
+ case BinaryExpr.ResolvedOpcode.NotInSeq:
+ return BinaryExpr.ResolvedOpcode.InSeq;
+ case BinaryExpr.ResolvedOpcode.NotInMultiSet:
+ return BinaryExpr.ResolvedOpcode.InMultiSet;
+ }
+
+ Contract.Assert(false);
+ throw new ArgumentException();
+ }
+
+ internal static Expression CleanupExprForInclusionInTrigger(Expression expr, out bool isKiller) {
+ isKiller = false;
+
+ if (!(expr is BinaryExpr)) {
+ return expr;
+ }
+
+ var bexpr = expr as BinaryExpr;
+
+ BinaryExpr new_expr = bexpr;
+ if (bexpr.Op == BinaryExpr.Opcode.NotIn) {
+ new_expr = new BinaryExpr(bexpr.tok, BinaryExpr.Opcode.In, bexpr.E0, bexpr.E1);
+ new_expr.ResolvedOp = RemoveNotInBinaryExprIn(bexpr.ResolvedOp);
+ new_expr.Type = bexpr.Type;
+ }
+
+ Expression returned_expr = new_expr;
+ if (new_expr.ResolvedOp == BinaryExpr.ResolvedOpcode.InMultiSet) {
+ returned_expr = new SeqSelectExpr(new_expr.tok, true, new_expr.E1, new_expr.E0, null);
+ returned_expr.Type = bexpr.Type;
+ isKiller = true; // [a in s] becomes [s[a] > 0], which is a trigger killer
+ }
+
+ return returned_expr;
+ }
+
+ internal static Expression CleanupExprForInclusionInTrigger(Expression expr) {
+ bool _;
+ return CleanupExprForInclusionInTrigger(expr, out _);
+ }
+ }
+}
diff --git a/Source/Dafny/Triggers/TriggersCollector.cs b/Source/Dafny/Triggers/TriggersCollector.cs new file mode 100644 index 00000000..08d33af6 --- /dev/null +++ b/Source/Dafny/Triggers/TriggersCollector.cs @@ -0,0 +1,230 @@ +using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Microsoft.Boogie;
+using System.Diagnostics.Contracts;
+using System.Diagnostics;
+
+namespace Microsoft.Dafny.Triggers {
+ class TriggerTerm {
+ internal Expression Expr { get; set; }
+ internal Expression OriginalExpr { get; set; }
+ internal ISet<IVariable> Variables { get; set; }
+
+ public override string ToString() {
+ return Printer.ExprToString(OriginalExpr);
+ }
+
+ internal static bool Eq(TriggerTerm t1, TriggerTerm t2) {
+ return ExprExtensions.ExpressionEq(t1.Expr, t2.Expr);
+ }
+ }
+
+ class TriggerCandidate {
+ internal List<TriggerTerm> Terms { get; set; }
+ internal string Annotation { get; set; }
+
+ internal TriggerCandidate(List<TriggerTerm> terms) {
+ this.Terms = terms;
+ }
+
+ public TriggerCandidate(TriggerCandidate candidate) {
+ this.Terms = candidate.Terms;
+ }
+
+ internal bool MentionsAll(List<BoundVar> vars) {
+ return vars.All(x => Terms.Any(term => term.Variables.Contains(x)));
+ }
+
+ private string Repr { get { return String.Join(", ", Terms); } }
+
+ public override string ToString() {
+ return "{" + Repr + "}" + (String.IsNullOrWhiteSpace(Annotation) ? "" : " (" + Annotation + ")");
+ }
+
+ internal IEnumerable<TriggerMatch> LoopingSubterms(QuantifierExpr quantifier) {
+ Contract.Requires(quantifier.SplitQuantifier == null); // Don't call this on a quantifier with a Split clause: it's not a real quantifier
+ var matchingSubterms = MatchingSubterms(quantifier);
+ return matchingSubterms.Where(tm => tm.CouldCauseLoops(Terms));
+ }
+
+ internal List<TriggerMatch> MatchingSubterms(QuantifierExpr quantifier) {
+ Contract.Requires(quantifier.SplitQuantifier == null); // Don't call this on a quantifier with a Split clause: it's not a real quantifier
+ return Terms.SelectMany(term => quantifier.SubexpressionsMatchingTrigger(term.Expr)).Deduplicate(TriggerMatch.Eq);
+ }
+
+ public String AsDafnyAttributeString() {
+ return "{:trigger " + Repr + "}";
+ }
+ }
+
+ class TriggerAnnotation {
+ internal bool IsTriggerKiller;
+ internal ISet<IVariable> Variables;
+ internal readonly List<TriggerTerm> PrivateTerms;
+ internal readonly List<TriggerTerm> ExportedTerms;
+
+ internal TriggerAnnotation(bool IsTriggerKiller, IEnumerable<IVariable> Variables, IEnumerable<TriggerTerm> AllTerms, IEnumerable<TriggerTerm> PrivateTerms = null) {
+ this.IsTriggerKiller = IsTriggerKiller;
+ this.Variables = new HashSet<IVariable>(Variables);
+ this.PrivateTerms = new List<TriggerTerm>(PrivateTerms == null ? Enumerable.Empty<TriggerTerm>() : PrivateTerms);
+ this.ExportedTerms = new List<TriggerTerm>(AllTerms == null ? Enumerable.Empty<TriggerTerm>() : AllTerms.Except(this.PrivateTerms));
+ }
+
+ public override string ToString() {
+ StringBuilder sb = new StringBuilder();
+ string indent = " {0}", nindent = "\n - {0}", subindent = "\n * {0}";
+
+ sb.AppendFormat(indent, IsTriggerKiller);
+
+ sb.AppendFormat(nindent, "Variables:");
+ foreach (var bv in Variables) {
+ sb.AppendFormat(subindent, bv.Name);
+ }
+
+ sb.AppendFormat(nindent, "Exported terms:");
+ foreach (var term in ExportedTerms) {
+ sb.AppendFormat(subindent, term);
+ }
+
+ if (PrivateTerms.Any()) {
+ sb.AppendFormat(nindent, "Private terms:");
+ foreach (var term in PrivateTerms) {
+ sb.AppendFormat(subindent, term);
+ }
+ }
+
+ return sb.ToString();
+ }
+ }
+
+ public class TriggersCollector {
+ Dictionary<Expression, TriggerAnnotation> cache;
+
+ internal TriggersCollector() {
+ this.cache = new Dictionary<Expression, TriggerAnnotation>();
+ }
+
+ private T ReduceAnnotatedSubExpressions<T>(Expression expr, T seed, Func<TriggerAnnotation, T> map, Func<T, T, T> reduce) {
+ return expr.SubExpressions.Select(e => map(Annotate(e)))
+ .Aggregate(seed, (acc, e) => reduce(acc, e));
+ }
+
+ private List<TriggerTerm> CollectExportedCandidates(Expression expr) {
+ return ReduceAnnotatedSubExpressions<List<TriggerTerm>>(expr, new List<TriggerTerm>(), a => a.ExportedTerms, TriggerUtils.MergeAlterFirst);
+ }
+
+ private ISet<IVariable> CollectVariables(Expression expr) {
+ return ReduceAnnotatedSubExpressions(expr, new HashSet<IVariable>(), a => a.Variables, TriggerUtils.MergeAlterFirst);
+ }
+
+ private bool CollectIsKiller(Expression expr) {
+ return ReduceAnnotatedSubExpressions(expr, false, a => a.IsTriggerKiller, (a, b) => a || b);
+ }
+
+ private IEnumerable<TriggerTerm> OnlyPrivateCandidates(List<TriggerTerm> terms, IEnumerable<IVariable> privateVars) {
+ return terms.Where(c => privateVars.Intersect(c.Variables).Any()); //TODO Check perf
+ }
+
+ private TriggerAnnotation Annotate(Expression expr) {
+ TriggerAnnotation cached;
+ if (cache.TryGetValue(expr, out cached)) {
+ return cached;
+ }
+
+ expr.SubExpressions.Iter(e => Annotate(e));
+
+ TriggerAnnotation annotation; // TODO: Using ApplySuffix fixes the unresolved members problem in GenericSort
+ if (expr is FunctionCallExpr || expr is SeqSelectExpr || expr is MemberSelectExpr || expr is OldExpr || expr is ApplyExpr ||
+ (expr is UnaryOpExpr && (((UnaryOpExpr)expr).Op == UnaryOpExpr.Opcode.Cardinality)) || // FIXME || ((UnaryOpExpr)expr).Op == UnaryOpExpr.Opcode.Fresh doesn't work, as fresh is a pretty tricky predicate when it's not about datatypes. See translator.cs:10944
+ (expr is BinaryExpr && (((BinaryExpr)expr).Op == BinaryExpr.Opcode.NotIn || ((BinaryExpr)expr).Op == BinaryExpr.Opcode.In))) {
+ annotation = AnnotatePotentialCandidate(expr);
+ } else if (expr is QuantifierExpr && ((QuantifierExpr)expr).SplitQuantifier == null) {
+ annotation = AnnotateQuantifier((QuantifierExpr)expr);
+ } else if (expr is LetExpr) {
+ annotation = AnnotateLetExpr((LetExpr)expr);
+ } else if (expr is IdentifierExpr) {
+ annotation = AnnotateIdentifier((IdentifierExpr)expr);
+ } else if (expr is ApplySuffix) {
+ annotation = AnnotateApplySuffix((ApplySuffix)expr);
+ } else if (expr is ConcreteSyntaxExpression ||
+ expr is LiteralExpr ||
+ expr is OldExpr ||
+ expr is ThisExpr ||
+ expr is BoxingCastExpr ||
+ expr is DatatypeValue ||
+ expr is SeqDisplayExpr) { //FIXME what abvout other display expressions?
+ annotation = AnnotateOther(expr, false);
+ } else {
+ annotation = AnnotateOther(expr, true);
+ }
+
+ TriggerUtils.DebugTriggers("{0} ({1})\n{2}", Printer.ExprToString(expr), expr.GetType(), annotation);
+ cache[expr] = annotation;
+ return annotation;
+ }
+
+ private TriggerAnnotation AnnotatePotentialCandidate(Expression expr) {
+ bool expr_is_killer = false;
+ var new_expr = TriggerUtils.CleanupExprForInclusionInTrigger(expr, out expr_is_killer);
+ var new_term = new TriggerTerm { Expr = new_expr, OriginalExpr = expr, Variables = CollectVariables(expr) };
+
+ List<TriggerTerm> collected_terms = CollectExportedCandidates(expr);
+ var children_contain_killers = CollectIsKiller(expr);
+
+ if (!children_contain_killers) {
+ // Add only if the children are not killers; the head has been cleaned up into non-killer form
+ collected_terms.Add(new_term);
+ }
+
+ // This new node is a killer if its children were killers, or if it's non-cleaned-up head is a killer
+ return new TriggerAnnotation(children_contain_killers || expr_is_killer, new_term.Variables, collected_terms);
+ }
+
+ private TriggerAnnotation AnnotateApplySuffix(ApplySuffix expr) {
+ // This is a bit tricky. A funcall node is generally meaningful as a trigger candidate,
+ // but when it's part of an ApplySuffix the function call itself may not resolve properly
+ // when the second round of resolving is done after modules are duplicated.
+ // Thus first we annotate expr and create a trigger candidate, and then we remove the
+ // candidate matching its direct subexpression if needed. Note that function calls are not the
+ // only possible child here; there can be DatatypeValue nodes, for example (see vstte2012/Combinators.dfy).
+ var annotation = AnnotatePotentialCandidate(expr);
+ // Comparing by reference is fine here. Using sets could yield a small speedup
+ annotation.ExportedTerms.RemoveAll(term => expr.SubExpressions.Contains(term.Expr));
+ return annotation;
+ }
+
+ private TriggerAnnotation AnnotateQuantifierOrLetExpr(Expression expr, IEnumerable<BoundVar> boundVars) {
+ var terms = CollectExportedCandidates(expr);
+ return new TriggerAnnotation(true, CollectVariables(expr), terms, OnlyPrivateCandidates(terms, boundVars));
+ }
+
+ private TriggerAnnotation AnnotateQuantifier(QuantifierExpr expr) {
+ return AnnotateQuantifierOrLetExpr(expr, expr.BoundVars);
+ }
+
+ private TriggerAnnotation AnnotateLetExpr(LetExpr expr) {
+ return AnnotateQuantifierOrLetExpr(expr, expr.BoundVars);
+ }
+
+ private TriggerAnnotation AnnotateIdentifier(IdentifierExpr expr) {
+ return new TriggerAnnotation(false, Enumerable.Repeat(expr.Var, 1), null);
+ }
+
+ private TriggerAnnotation AnnotateOther(Expression expr, bool isTriggerKiller) {
+ return new TriggerAnnotation(isTriggerKiller || CollectIsKiller(expr), CollectVariables(expr), CollectExportedCandidates(expr));
+ }
+
+ // FIXME document that this will contain duplicates
+ internal List<TriggerTerm> CollectTriggers(QuantifierExpr quantifier) {
+ Contract.Requires(quantifier.SplitQuantifier == null); // Don't call this on a quantifier with a Split clause: it's not a real quantifier
+ // TODO could check for existing triggers and return that instead, but that require a bit of work to extract the expressions
+ return Annotate(quantifier).PrivateTerms;
+ }
+
+ internal bool IsTriggerKiller(Expression expr) {
+ return Annotate(expr).IsTriggerKiller;
+ }
+ }
+}
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 ?? "");
- }
-
/// <summary>
/// Returns s but with all occurrences of '_' removed.
/// </summary>
|