summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar stefanheule <unknown>2012-03-09 02:33:36 -0800
committerGravatar stefanheule <unknown>2012-03-09 02:33:36 -0800
commit1edc06c71b783d4a70d3e0e8a011fc47e78d3c3a (patch)
treec0cd27c346d06c7111f6ae6e127cfae8e7fadac2
parent55b69a7c7d029c9fbd607f563ecd23087141b298 (diff)
parent68f2b9caf8b5d64399eb8e74daf75788bec74e4f (diff)
Automatic merge.
-rw-r--r--.hgtags1
-rw-r--r--BCT/BytecodeTranslator/Sink.cs3
-rw-r--r--Chalice/src/main/scala/Translator.scala2
-rw-r--r--Source/Boogie.sln83
-rw-r--r--Source/BoogieDriver/BoogieDriver.cs376
-rw-r--r--Source/BoogieDriver/BoogieDriver.csproj12
-rw-r--r--Source/Core/CommandLineOptions.cs15
-rw-r--r--Source/Dafny/Compiler.cs6
-rw-r--r--Source/Dafny/Dafny.atg77
-rw-r--r--Source/Dafny/DafnyAst.cs217
-rw-r--r--Source/Dafny/DafnyPipeline.csproj1
-rw-r--r--Source/Dafny/Parser.cs344
-rw-r--r--Source/Dafny/Printer.cs8
-rw-r--r--Source/Dafny/RefinementTransformer.cs246
-rw-r--r--Source/Dafny/Resolver.cs13
-rw-r--r--Source/Dafny/Rewriter.cs321
-rw-r--r--Source/Dafny/Scanner.cs10
-rw-r--r--Source/Dafny/Translator.cs19
-rw-r--r--Source/GPUVerify.sln110
-rw-r--r--Source/GPUVerify/AccessInvariantProcessor.cs107
-rw-r--r--Source/GPUVerify/AsymmetricExpressionFinder.cs29
-rw-r--r--Source/GPUVerify/CrossThreadInvariantProcessor.cs53
-rw-r--r--Source/GPUVerify/ElementEncodingRaceInstrumenter.cs26
-rw-r--r--Source/GPUVerify/EnabledToPredicateVisitor.cs39
-rw-r--r--Source/GPUVerify/GPUVerifier.cs511
-rw-r--r--Source/GPUVerify/GPUVerify.csproj5
-rw-r--r--Source/GPUVerify/IRaceInstrumenter.cs6
-rw-r--r--Source/GPUVerify/NullRaceInstrumenter.cs15
-rw-r--r--Source/GPUVerify/Predicator.cs262
-rw-r--r--Source/GPUVerify/RaceInstrumenterBase.cs72
-rw-r--r--Source/GPUVerify/SetEncodingRaceInstrumenter.cs16
-rw-r--r--Source/GPUVerify/StructuredProgramVisitor.cs152
-rw-r--r--Source/GPUVerify/VariableDualiser.cs23
-rw-r--r--Source/Houdini/Checker.cs39
-rw-r--r--Source/Houdini/Houdini.cs265
-rw-r--r--Source/Houdini/Houdini.csproj8
-rw-r--r--Source/Provers/SMTLib/Inspector.cs1
-rw-r--r--Source/Provers/SMTLib/ProverInterface.cs216
-rw-r--r--Source/Provers/SMTLib/SMTLib.csproj4
-rw-r--r--Source/Provers/TPTP/TPTP.csproj4
-rw-r--r--Source/Provers/Z3api/ProverLayer.cs153
-rw-r--r--Source/Provers/Z3api/Z3api.csproj8
-rw-r--r--Source/VCGeneration/Check.cs57
-rw-r--r--Source/VCGeneration/StratifiedVC.cs471
-rw-r--r--Source/VCGeneration/VC.cs89
-rw-r--r--Source/VCGeneration/Wlp.cs12
-rw-r--r--Test/dafny0/Answer20
-rw-r--r--Test/dafny0/LetExpr.dfy40
-rw-r--r--Test/dafny0/Skeletons.dfy63
-rw-r--r--Test/dafny0/runtest.bat2
-rw-r--r--Test/dafny1/Answer4
-rw-r--r--Test/dafny1/ExtensibleArrayAuto.dfy113
-rw-r--r--Test/dafny1/runtest.bat3
-rw-r--r--Test/houdini/Answer14
-rw-r--r--Test/houdini/runtest.bat4
-rw-r--r--Test/vstte2012/Answer4
-rw-r--r--Test/vstte2012/RingBufferAuto.dfy75
-rw-r--r--Test/vstte2012/runtest.bat2
-rw-r--r--_admin/Boogie/aste/summary.log22
59 files changed, 3281 insertions, 1592 deletions
diff --git a/.hgtags b/.hgtags
index de9a92e1..50119793 100644
--- a/.hgtags
+++ b/.hgtags
@@ -12,3 +12,4 @@ f5c14add09d2f57402c94574eeef490d900d58e8 emicvccbld_build_2.1.31109.0
a25a1feb48848a6cac9ab0fd6480871ad5e9a881 emicvccbld_build_2.1.31116.0
e2af2d88d523eebe5e183839ed9d32c9d5ace55a emicvccbld_build_2.1.31203.0
019becd8203f71f3f28368f87e14421cba209b3b emicvccbld_build_2.1.31207.0
+4afa7ea66506aed88223d4236cb3d7cff870abf8 emicvccbld_build_2.1.40227.0
diff --git a/BCT/BytecodeTranslator/Sink.cs b/BCT/BytecodeTranslator/Sink.cs
index 61d5e977..7a1abc07 100644
--- a/BCT/BytecodeTranslator/Sink.cs
+++ b/BCT/BytecodeTranslator/Sink.cs
@@ -330,6 +330,9 @@ namespace BytecodeTranslator {
var name = "$string_literal_" + TranslationHelper.TurnStringIntoValidIdentifier(str) + "_" + declaredStringConstants.Count;
var tident = new Bpl.TypedIdent(tok, name, t);
c = new Bpl.Constant(tok, tident, true);
+ str = str.Replace("\n", "\\n");
+ var attrib = new Bpl.QKeyValue(Bpl.Token.NoToken, "value", new List<object> { str, }, null);
+ c.Attributes = attrib;
this.declaredStringConstants.Add(str, c);
this.TranslatedProgram.TopLevelDeclarations.Add(c);
}
diff --git a/Chalice/src/main/scala/Translator.scala b/Chalice/src/main/scala/Translator.scala
index cf7e85aa..95996ee9 100644
--- a/Chalice/src/main/scala/Translator.scala
+++ b/Chalice/src/main/scala/Translator.scala
@@ -3038,7 +3038,7 @@ object TranslationHelper {
}
def SubstRd(e: Expression): Expression = e match {
- case Access(e, _:Permission) =>
+ case Access(e, p: Permission) if p != Star =>
//val r = Access(e,MonitorEpsilon(None)); r.pos = e.pos; r.typ = BoolClass; r
val r = Access(e,Epsilons(IntLiteral(1))); r.pos = e.pos; r.typ = BoolClass; r
case Implies(e0,e1) =>
diff --git a/Source/Boogie.sln b/Source/Boogie.sln
index 53130382..955dfb46 100644
--- a/Source/Boogie.sln
+++ b/Source/Boogie.sln
@@ -9,12 +9,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Isabelle", "Provers\Isabell
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AbsInt", "AbsInt\AbsInt.csproj", "{0EFA3E43-690B-48DC-A72C-384A3EA7F31F}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Z3", "Provers\Z3\Z3.csproj", "{BB49B90B-BE21-4BE8-85BA-359FDB55F4DF}"
-EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SMTLib", "Provers\SMTLib\SMTLib.csproj", "{9B163AA3-36BC-4AFB-88AB-79BC9E97E401}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Simplify", "Provers\Simplify\Simplify.csproj", "{FEE9F01B-9722-4A76-A24B-72A4016DFA8E}"
-EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VCGeneration", "VCGeneration\VCGeneration.csproj", "{E1F10180-C7B9-4147-B51F-FA1B701966DC}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VCExpr", "VCExpr\VCExpr.csproj", "{56FFDBCA-7D14-43B8-A6CA-22A20E417EE1}"
@@ -37,8 +33,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Model", "Model\Model.csproj
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ParserHelper", "ParserHelper\ParserHelper.csproj", "{FCD3AC7F-9DFD-46C8-AB1E-09F0B0F16DC5}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TPTP", "Provers\TPTP\TPTP.csproj", "{A598ED5A-93AD-4125-A555-3921A2F936FA}"
-EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Houdini", "Houdini\Houdini.csproj", "{CF41E903-78EB-43BA-A355-E5FEB5ECECD4}"
EndProject
Global
@@ -136,31 +130,6 @@ Global
{0EFA3E43-690B-48DC-A72C-384A3EA7F31F}.z3apidebug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{0EFA3E43-690B-48DC-A72C-384A3EA7F31F}.z3apidebug|Mixed Platforms.Build.0 = Debug|Any CPU
{0EFA3E43-690B-48DC-A72C-384A3EA7F31F}.z3apidebug|x86.ActiveCfg = z3apidebug|Any CPU
- {BB49B90B-BE21-4BE8-85BA-359FDB55F4DF}.Checked|.NET.ActiveCfg = Checked|Any CPU
- {BB49B90B-BE21-4BE8-85BA-359FDB55F4DF}.Checked|Any CPU.ActiveCfg = Checked|Any CPU
- {BB49B90B-BE21-4BE8-85BA-359FDB55F4DF}.Checked|Any CPU.Build.0 = Checked|Any CPU
- {BB49B90B-BE21-4BE8-85BA-359FDB55F4DF}.Checked|Mixed Platforms.ActiveCfg = Checked|Any CPU
- {BB49B90B-BE21-4BE8-85BA-359FDB55F4DF}.Checked|Mixed Platforms.Build.0 = Checked|Any CPU
- {BB49B90B-BE21-4BE8-85BA-359FDB55F4DF}.Checked|x86.ActiveCfg = Checked|Any CPU
- {BB49B90B-BE21-4BE8-85BA-359FDB55F4DF}.Debug|.NET.ActiveCfg = Debug|Any CPU
- {BB49B90B-BE21-4BE8-85BA-359FDB55F4DF}.Debug|.NET.Build.0 = Debug|Any CPU
- {BB49B90B-BE21-4BE8-85BA-359FDB55F4DF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {BB49B90B-BE21-4BE8-85BA-359FDB55F4DF}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {BB49B90B-BE21-4BE8-85BA-359FDB55F4DF}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
- {BB49B90B-BE21-4BE8-85BA-359FDB55F4DF}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
- {BB49B90B-BE21-4BE8-85BA-359FDB55F4DF}.Debug|x86.ActiveCfg = Debug|Any CPU
- {BB49B90B-BE21-4BE8-85BA-359FDB55F4DF}.Release|.NET.ActiveCfg = Release|Any CPU
- {BB49B90B-BE21-4BE8-85BA-359FDB55F4DF}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {BB49B90B-BE21-4BE8-85BA-359FDB55F4DF}.Release|Any CPU.Build.0 = Release|Any CPU
- {BB49B90B-BE21-4BE8-85BA-359FDB55F4DF}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
- {BB49B90B-BE21-4BE8-85BA-359FDB55F4DF}.Release|Mixed Platforms.Build.0 = Release|Any CPU
- {BB49B90B-BE21-4BE8-85BA-359FDB55F4DF}.Release|x86.ActiveCfg = Release|Any CPU
- {BB49B90B-BE21-4BE8-85BA-359FDB55F4DF}.z3apidebug|.NET.ActiveCfg = z3apidebug|Any CPU
- {BB49B90B-BE21-4BE8-85BA-359FDB55F4DF}.z3apidebug|Any CPU.ActiveCfg = z3apidebug|Any CPU
- {BB49B90B-BE21-4BE8-85BA-359FDB55F4DF}.z3apidebug|Any CPU.Build.0 = z3apidebug|Any CPU
- {BB49B90B-BE21-4BE8-85BA-359FDB55F4DF}.z3apidebug|Mixed Platforms.ActiveCfg = Debug|Any CPU
- {BB49B90B-BE21-4BE8-85BA-359FDB55F4DF}.z3apidebug|Mixed Platforms.Build.0 = Debug|Any CPU
- {BB49B90B-BE21-4BE8-85BA-359FDB55F4DF}.z3apidebug|x86.ActiveCfg = z3apidebug|Any CPU
{9B163AA3-36BC-4AFB-88AB-79BC9E97E401}.Checked|.NET.ActiveCfg = Checked|Any CPU
{9B163AA3-36BC-4AFB-88AB-79BC9E97E401}.Checked|Any CPU.ActiveCfg = Checked|Any CPU
{9B163AA3-36BC-4AFB-88AB-79BC9E97E401}.Checked|Any CPU.Build.0 = Checked|Any CPU
@@ -186,31 +155,6 @@ Global
{9B163AA3-36BC-4AFB-88AB-79BC9E97E401}.z3apidebug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{9B163AA3-36BC-4AFB-88AB-79BC9E97E401}.z3apidebug|Mixed Platforms.Build.0 = Debug|Any CPU
{9B163AA3-36BC-4AFB-88AB-79BC9E97E401}.z3apidebug|x86.ActiveCfg = z3apidebug|Any CPU
- {FEE9F01B-9722-4A76-A24B-72A4016DFA8E}.Checked|.NET.ActiveCfg = Checked|Any CPU
- {FEE9F01B-9722-4A76-A24B-72A4016DFA8E}.Checked|Any CPU.ActiveCfg = Checked|Any CPU
- {FEE9F01B-9722-4A76-A24B-72A4016DFA8E}.Checked|Any CPU.Build.0 = Checked|Any CPU
- {FEE9F01B-9722-4A76-A24B-72A4016DFA8E}.Checked|Mixed Platforms.ActiveCfg = Checked|Any CPU
- {FEE9F01B-9722-4A76-A24B-72A4016DFA8E}.Checked|Mixed Platforms.Build.0 = Checked|Any CPU
- {FEE9F01B-9722-4A76-A24B-72A4016DFA8E}.Checked|x86.ActiveCfg = Checked|Any CPU
- {FEE9F01B-9722-4A76-A24B-72A4016DFA8E}.Debug|.NET.ActiveCfg = Debug|Any CPU
- {FEE9F01B-9722-4A76-A24B-72A4016DFA8E}.Debug|.NET.Build.0 = Debug|Any CPU
- {FEE9F01B-9722-4A76-A24B-72A4016DFA8E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {FEE9F01B-9722-4A76-A24B-72A4016DFA8E}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {FEE9F01B-9722-4A76-A24B-72A4016DFA8E}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
- {FEE9F01B-9722-4A76-A24B-72A4016DFA8E}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
- {FEE9F01B-9722-4A76-A24B-72A4016DFA8E}.Debug|x86.ActiveCfg = Debug|Any CPU
- {FEE9F01B-9722-4A76-A24B-72A4016DFA8E}.Release|.NET.ActiveCfg = Release|Any CPU
- {FEE9F01B-9722-4A76-A24B-72A4016DFA8E}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {FEE9F01B-9722-4A76-A24B-72A4016DFA8E}.Release|Any CPU.Build.0 = Release|Any CPU
- {FEE9F01B-9722-4A76-A24B-72A4016DFA8E}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
- {FEE9F01B-9722-4A76-A24B-72A4016DFA8E}.Release|Mixed Platforms.Build.0 = Release|Any CPU
- {FEE9F01B-9722-4A76-A24B-72A4016DFA8E}.Release|x86.ActiveCfg = Release|Any CPU
- {FEE9F01B-9722-4A76-A24B-72A4016DFA8E}.z3apidebug|.NET.ActiveCfg = z3apidebug|Any CPU
- {FEE9F01B-9722-4A76-A24B-72A4016DFA8E}.z3apidebug|Any CPU.ActiveCfg = z3apidebug|Any CPU
- {FEE9F01B-9722-4A76-A24B-72A4016DFA8E}.z3apidebug|Any CPU.Build.0 = z3apidebug|Any CPU
- {FEE9F01B-9722-4A76-A24B-72A4016DFA8E}.z3apidebug|Mixed Platforms.ActiveCfg = Debug|Any CPU
- {FEE9F01B-9722-4A76-A24B-72A4016DFA8E}.z3apidebug|Mixed Platforms.Build.0 = Debug|Any CPU
- {FEE9F01B-9722-4A76-A24B-72A4016DFA8E}.z3apidebug|x86.ActiveCfg = z3apidebug|Any CPU
{E1F10180-C7B9-4147-B51F-FA1B701966DC}.Checked|.NET.ActiveCfg = Checked|Any CPU
{E1F10180-C7B9-4147-B51F-FA1B701966DC}.Checked|Any CPU.ActiveCfg = Checked|Any CPU
{E1F10180-C7B9-4147-B51F-FA1B701966DC}.Checked|Any CPU.Build.0 = Checked|Any CPU
@@ -473,30 +417,6 @@ Global
{FCD3AC7F-9DFD-46C8-AB1E-09F0B0F16DC5}.z3apidebug|Mixed Platforms.ActiveCfg = Release|Any CPU
{FCD3AC7F-9DFD-46C8-AB1E-09F0B0F16DC5}.z3apidebug|Mixed Platforms.Build.0 = Release|Any CPU
{FCD3AC7F-9DFD-46C8-AB1E-09F0B0F16DC5}.z3apidebug|x86.ActiveCfg = Release|Any CPU
- {A598ED5A-93AD-4125-A555-3921A2F936FA}.Checked|.NET.ActiveCfg = Checked|Any CPU
- {A598ED5A-93AD-4125-A555-3921A2F936FA}.Checked|Any CPU.ActiveCfg = Checked|Any CPU
- {A598ED5A-93AD-4125-A555-3921A2F936FA}.Checked|Any CPU.Build.0 = Checked|Any CPU
- {A598ED5A-93AD-4125-A555-3921A2F936FA}.Checked|Mixed Platforms.ActiveCfg = Checked|Any CPU
- {A598ED5A-93AD-4125-A555-3921A2F936FA}.Checked|Mixed Platforms.Build.0 = Checked|Any CPU
- {A598ED5A-93AD-4125-A555-3921A2F936FA}.Checked|x86.ActiveCfg = Checked|Any CPU
- {A598ED5A-93AD-4125-A555-3921A2F936FA}.Debug|.NET.ActiveCfg = Debug|Any CPU
- {A598ED5A-93AD-4125-A555-3921A2F936FA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {A598ED5A-93AD-4125-A555-3921A2F936FA}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {A598ED5A-93AD-4125-A555-3921A2F936FA}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
- {A598ED5A-93AD-4125-A555-3921A2F936FA}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
- {A598ED5A-93AD-4125-A555-3921A2F936FA}.Debug|x86.ActiveCfg = Debug|Any CPU
- {A598ED5A-93AD-4125-A555-3921A2F936FA}.Release|.NET.ActiveCfg = Release|Any CPU
- {A598ED5A-93AD-4125-A555-3921A2F936FA}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {A598ED5A-93AD-4125-A555-3921A2F936FA}.Release|Any CPU.Build.0 = Release|Any CPU
- {A598ED5A-93AD-4125-A555-3921A2F936FA}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
- {A598ED5A-93AD-4125-A555-3921A2F936FA}.Release|Mixed Platforms.Build.0 = Release|Any CPU
- {A598ED5A-93AD-4125-A555-3921A2F936FA}.Release|x86.ActiveCfg = Release|Any CPU
- {A598ED5A-93AD-4125-A555-3921A2F936FA}.z3apidebug|.NET.ActiveCfg = Release|Any CPU
- {A598ED5A-93AD-4125-A555-3921A2F936FA}.z3apidebug|Any CPU.ActiveCfg = Release|Any CPU
- {A598ED5A-93AD-4125-A555-3921A2F936FA}.z3apidebug|Any CPU.Build.0 = Release|Any CPU
- {A598ED5A-93AD-4125-A555-3921A2F936FA}.z3apidebug|Mixed Platforms.ActiveCfg = Release|Any CPU
- {A598ED5A-93AD-4125-A555-3921A2F936FA}.z3apidebug|Mixed Platforms.Build.0 = Release|Any CPU
- {A598ED5A-93AD-4125-A555-3921A2F936FA}.z3apidebug|x86.ActiveCfg = Release|Any CPU
{CF41E903-78EB-43BA-A355-E5FEB5ECECD4}.Checked|.NET.ActiveCfg = Release|Any CPU
{CF41E903-78EB-43BA-A355-E5FEB5ECECD4}.Checked|Any CPU.ActiveCfg = Release|Any CPU
{CF41E903-78EB-43BA-A355-E5FEB5ECECD4}.Checked|Any CPU.Build.0 = Release|Any CPU
@@ -527,10 +447,7 @@ Global
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{435D5BD0-6F62-49F8-BB24-33E2257519AD} = {B758C1E3-824A-439F-AA2F-0BA1143E8C8D}
- {BB49B90B-BE21-4BE8-85BA-359FDB55F4DF} = {B758C1E3-824A-439F-AA2F-0BA1143E8C8D}
{9B163AA3-36BC-4AFB-88AB-79BC9E97E401} = {B758C1E3-824A-439F-AA2F-0BA1143E8C8D}
- {FEE9F01B-9722-4A76-A24B-72A4016DFA8E} = {B758C1E3-824A-439F-AA2F-0BA1143E8C8D}
{966DD87B-A29D-4F3C-9406-F680A61DC0E0} = {B758C1E3-824A-439F-AA2F-0BA1143E8C8D}
- {A598ED5A-93AD-4125-A555-3921A2F936FA} = {B758C1E3-824A-439F-AA2F-0BA1143E8C8D}
EndGlobalSection
EndGlobal
diff --git a/Source/BoogieDriver/BoogieDriver.cs b/Source/BoogieDriver/BoogieDriver.cs
index c2c09ded..b765a1c3 100644
--- a/Source/BoogieDriver/BoogieDriver.cs
+++ b/Source/BoogieDriver/BoogieDriver.cs
@@ -429,6 +429,134 @@ namespace Microsoft.Boogie {
}
}
+ static void ProcessOutcome(VC.VCGen.Outcome outcome, List<Counterexample> errors, string timeIndication,
+ ref int errorCount, ref int verified, ref int inconclusives, ref int timeOuts, ref int outOfMemories) {
+ switch (outcome) {
+ default:
+ Contract.Assert(false); // unexpected outcome
+ throw new cce.UnreachableException();
+ case VCGen.Outcome.ReachedBound:
+ Inform(String.Format("{0}verified", timeIndication));
+ Console.WriteLine(string.Format("Stratified Inlining: Reached recursion bound of {0}", CommandLineOptions.Clo.RecursionBound));
+ verified++;
+ break;
+ case VCGen.Outcome.Correct:
+ if (CommandLineOptions.Clo.vcVariety == CommandLineOptions.VCVariety.Doomed) {
+ Inform(String.Format("{0}credible", timeIndication));
+ verified++;
+ }
+ else {
+ Inform(String.Format("{0}verified", timeIndication));
+ verified++;
+ }
+ break;
+ case VCGen.Outcome.TimedOut:
+ timeOuts++;
+ Inform(String.Format("{0}timed out", timeIndication));
+ break;
+ case VCGen.Outcome.OutOfMemory:
+ outOfMemories++;
+ Inform(String.Format("{0}out of memory", timeIndication));
+ break;
+ case VCGen.Outcome.Inconclusive:
+ inconclusives++;
+ Inform(String.Format("{0}inconclusive", timeIndication));
+ break;
+ case VCGen.Outcome.Errors:
+ if (CommandLineOptions.Clo.vcVariety == CommandLineOptions.VCVariety.Doomed) {
+ Inform(String.Format("{0}doomed", timeIndication));
+ errorCount++;
+ } //else {
+ Contract.Assert(errors != null); // guaranteed by postcondition of VerifyImplementation
+
+ {
+ // BP1xxx: Parsing errors
+ // BP2xxx: Name resolution errors
+ // BP3xxx: Typechecking errors
+ // BP4xxx: Abstract interpretation errors (Is there such a thing?)
+ // BP5xxx: Verification errors
+
+ errors.Sort(new CounterexampleComparer());
+ foreach (Counterexample error in errors) {
+ if (error is CallCounterexample) {
+ CallCounterexample err = (CallCounterexample)error;
+ if (!CommandLineOptions.Clo.ForceBplErrors && err.FailingRequires.ErrorMessage != null) {
+ ReportBplError(err.FailingRequires, err.FailingRequires.ErrorMessage, true, false);
+ }
+ else {
+ ReportBplError(err.FailingCall, "Error BP5002: A precondition for this call might not hold.", true, true);
+ ReportBplError(err.FailingRequires, "Related location: This is the precondition that might not hold.", false, true);
+ }
+ if (CommandLineOptions.Clo.XmlSink != null) {
+ CommandLineOptions.Clo.XmlSink.WriteError("precondition violation", err.FailingCall.tok, err.FailingRequires.tok, error.Trace);
+ }
+ }
+ else if (error is ReturnCounterexample) {
+ ReturnCounterexample err = (ReturnCounterexample)error;
+ if (!CommandLineOptions.Clo.ForceBplErrors && err.FailingEnsures.ErrorMessage != null) {
+ ReportBplError(err.FailingEnsures, err.FailingEnsures.ErrorMessage, true, false);
+ }
+ else {
+ ReportBplError(err.FailingReturn, "Error BP5003: A postcondition might not hold on this return path.", true, true);
+ ReportBplError(err.FailingEnsures, "Related location: This is the postcondition that might not hold.", false, true);
+ }
+ if (CommandLineOptions.Clo.XmlSink != null) {
+ CommandLineOptions.Clo.XmlSink.WriteError("postcondition violation", err.FailingReturn.tok, err.FailingEnsures.tok, error.Trace);
+ }
+ }
+ else // error is AssertCounterexample
+ {
+ AssertCounterexample err = (AssertCounterexample)error;
+ if (err.FailingAssert is LoopInitAssertCmd) {
+ ReportBplError(err.FailingAssert, "Error BP5004: This loop invariant might not hold on entry.", true, true);
+ if (CommandLineOptions.Clo.XmlSink != null) {
+ CommandLineOptions.Clo.XmlSink.WriteError("loop invariant entry violation", err.FailingAssert.tok, null, error.Trace);
+ }
+ }
+ else if (err.FailingAssert is LoopInvMaintainedAssertCmd) {
+ // this assertion is a loop invariant which is not maintained
+ ReportBplError(err.FailingAssert, "Error BP5005: This loop invariant might not be maintained by the loop.", true, true);
+ if (CommandLineOptions.Clo.XmlSink != null) {
+ CommandLineOptions.Clo.XmlSink.WriteError("loop invariant maintenance violation", err.FailingAssert.tok, null, error.Trace);
+ }
+ }
+ else {
+ if (!CommandLineOptions.Clo.ForceBplErrors && err.FailingAssert.ErrorMessage != null) {
+ ReportBplError(err.FailingAssert, err.FailingAssert.ErrorMessage, true, false);
+ }
+ else if (err.FailingAssert.ErrorData is string) {
+ ReportBplError(err.FailingAssert, (string)err.FailingAssert.ErrorData, true, true);
+ }
+ else {
+ ReportBplError(err.FailingAssert, "Error BP5001: This assertion might not hold.", true, true);
+ }
+ if (CommandLineOptions.Clo.XmlSink != null) {
+ CommandLineOptions.Clo.XmlSink.WriteError("assertion violation", err.FailingAssert.tok, null, error.Trace);
+ }
+ }
+ }
+ if (CommandLineOptions.Clo.EnhancedErrorMessages == 1) {
+ foreach (string info in error.relatedInformation) {
+ Contract.Assert(info != null);
+ Console.WriteLine(" " + info);
+ }
+ }
+ if (CommandLineOptions.Clo.ErrorTrace > 0) {
+ Console.WriteLine("Execution trace:");
+ error.Print(4);
+ }
+ if (CommandLineOptions.Clo.ModelViewFile != null) {
+ error.PrintModel();
+ }
+ errorCount++;
+ }
+ //}
+ Inform(String.Format("{0}error{1}", timeIndication, errors.Count == 1 ? "" : "s"));
+ }
+ break;
+ }
+ }
+
/// <summary>
/// Given a resolved and type checked Boogie program, infers invariants for the program
/// and then attempts to verify it. Returns:
@@ -443,11 +571,6 @@ namespace Microsoft.Boogie {
Contract.Ensures(0 <= Contract.ValueAtReturn(out inconclusives) && 0 <= Contract.ValueAtReturn(out timeOuts));
errorCount = verified = inconclusives = timeOuts = outOfMemories = 0;
- CommandLineOptions.Clo.UseLabels =
- CommandLineOptions.Clo.UseLabels ||
- CommandLineOptions.Clo.SoundnessSmokeTest ||
- !(CommandLineOptions.Clo.vcVariety == CommandLineOptions.VCVariety.Dag ||
- CommandLineOptions.Clo.vcVariety == CommandLineOptions.VCVariety.DagIterative);
// ---------- Infer invariants --------------------------------------------------------
@@ -458,30 +581,6 @@ namespace Microsoft.Boogie {
Microsoft.Boogie.AbstractInterpretation.AbstractInterpretation.RunAbstractInterpretation(program);
}
- if (CommandLineOptions.Clo.ContractInfer) {
- Houdini.Houdini houdini = new Houdini.Houdini(program, true);
- Houdini.HoudiniOutcome outcome = houdini.PerformHoudiniInference();
- int numTrueAssigns = 0;
- Console.WriteLine("Assignment computed by Houdini:");
- foreach (var x in outcome.assignment) {
- Console.WriteLine(x.Key + " = " + x.Value);
- if (x.Value)
- numTrueAssigns++;
- }
- if (CommandLineOptions.Clo.Trace) {
- Console.WriteLine("Number of true assignments = " + numTrueAssigns);
- Console.WriteLine("Number of false assignments = " + (outcome.assignment.Count - numTrueAssigns));
- Console.WriteLine("Prover time = " + Houdini.HoudiniSession.proverTime);
- Console.WriteLine("Number of prover queries = " + Houdini.HoudiniSession.numProverQueries);
- }
- errorCount = outcome.ErrorCount;
- verified = outcome.Verified;
- inconclusives = outcome.Inconclusives;
- timeOuts = outcome.TimeOuts;
- outOfMemories = 0;
- return PipelineOutcome.Done;
- }
-
if (CommandLineOptions.Clo.LoopUnrollCount != -1) {
program.UnrollLoops(CommandLineOptions.Clo.LoopUnrollCount);
}
@@ -507,14 +606,41 @@ namespace Microsoft.Boogie {
return PipelineOutcome.Done;
}
- #region Verify each implementation
+ #region Run Houdini and verify
+ if (CommandLineOptions.Clo.ContractInfer) {
+ Houdini.Houdini houdini = new Houdini.Houdini(program, true);
+ Houdini.HoudiniOutcome outcome = houdini.PerformHoudiniInference();
+ if (CommandLineOptions.Clo.PrintAssignment) {
+ Console.WriteLine("Assignment computed by Houdini:");
+ foreach (var x in outcome.assignment) {
+ Console.WriteLine(x.Key + " = " + x.Value);
+ }
+ }
+ if (CommandLineOptions.Clo.Trace) {
+ int numTrueAssigns = 0;
+ foreach (var x in outcome.assignment) {
+ if (x.Value)
+ numTrueAssigns++;
+ }
+ Console.WriteLine("Number of true assignments = " + numTrueAssigns);
+ Console.WriteLine("Number of false assignments = " + (outcome.assignment.Count - numTrueAssigns));
+ Console.WriteLine("Prover time = " + Houdini.HoudiniSession.proverTime);
+ Console.WriteLine("Number of prover queries = " + Houdini.HoudiniSession.numProverQueries);
+ }
-#if ROB_DEBUG
- string now = DateTime.Now.ToString().Replace(' ','-').Replace('/','-').Replace(':','-');
- System.IO.StreamWriter w = new System.IO.StreamWriter(@"\temp\batch_"+now+".bpl");
- program.Emit(new TokenTextWriter(w));
- w.Close();
-#endif
+ foreach (Houdini.VCGenOutcome x in outcome.implementationOutcomes.Values) {
+ ProcessOutcome(x.outcome, x.errors, "", ref errorCount, ref verified, ref inconclusives, ref timeOuts, ref outOfMemories);
+ }
+ //errorCount = outcome.ErrorCount;
+ //verified = outcome.Verified;
+ //inconclusives = outcome.Inconclusives;
+ //timeOuts = outcome.TimeOuts;
+ //outOfMemories = 0;
+ return PipelineOutcome.Done;
+ }
+ #endregion
+
+ #region Verify each implementation
ConditionGeneration vcgen = null;
try {
@@ -553,42 +679,44 @@ namespace Microsoft.Boogie {
VCGen.Outcome outcome;
try {
- if (CommandLineOptions.Clo.inferLeastForUnsat != null)
- {
- var svcgen = vcgen as VC.StratifiedVCGen;
- Contract.Assert(svcgen != null);
- var ss = new HashSet<string>();
- foreach (var tdecl in program.TopLevelDeclarations)
- {
- var c = tdecl as Constant;
- if (c == null || !c.Name.StartsWith(CommandLineOptions.Clo.inferLeastForUnsat)) continue;
- ss.Add(c.Name);
- }
- outcome = svcgen.FindLeastToVerify(impl, program, ref ss);
- errors = new List<Counterexample>();
- Console.Write("Result: ");
- foreach (var s in ss)
- {
- Console.Write("{0} ", s);
- }
- Console.WriteLine();
+ if (CommandLineOptions.Clo.inferLeastForUnsat != null) {
+ var svcgen = vcgen as VC.StratifiedVCGen;
+ Contract.Assert(svcgen != null);
+ var ss = new HashSet<string>();
+ foreach (var tdecl in program.TopLevelDeclarations) {
+ var c = tdecl as Constant;
+ if (c == null || !c.Name.StartsWith(CommandLineOptions.Clo.inferLeastForUnsat)) continue;
+ ss.Add(c.Name);
}
- else
- {
- outcome = vcgen.VerifyImplementation(impl, program, out errors);
+ outcome = svcgen.FindLeastToVerify(impl, program, ref ss);
+ errors = new List<Counterexample>();
+ Console.Write("Result: ");
+ foreach (var s in ss) {
+ Console.Write("{0} ", s);
+ }
+ Console.WriteLine();
+ }
+ else {
+ outcome = vcgen.VerifyImplementation(impl, program, out errors);
+ if (CommandLineOptions.Clo.ExtractLoops && vcgen is VCGen && errors != null) {
+ for (int i = 0; i < errors.Count; i++) {
+ errors[i] = (vcgen as VCGen).extractLoopTrace(errors[i], impl.Name, program, extractLoopMappingInfo);
+ }
}
- } catch (VCGenException e) {
+ }
+ }
+ catch (VCGenException e) {
ReportBplError(impl, String.Format("Error BP5010: {0} Encountered in implementation {1}.", e.Message, impl.Name), true, true);
errors = null;
outcome = VCGen.Outcome.Inconclusive;
- } catch (UnexpectedProverOutputException upo) {
+ }
+ catch (UnexpectedProverOutputException upo) {
AdvisoryWriteLine("Advisory: {0} SKIPPED because of internal error: unexpected prover output: {1}", impl.Name, upo.Message);
errors = null;
outcome = VCGen.Outcome.Inconclusive;
}
string timeIndication = "";
-
DateTime end = DateTime.UtcNow;
TimeSpan elapsed = end - start;
if (CommandLineOptions.Clo.Trace || CommandLineOptions.Clo.XmlSink != null) {
@@ -598,130 +726,8 @@ namespace Microsoft.Boogie {
}
}
+ ProcessOutcome(outcome, errors, timeIndication, ref errorCount, ref verified, ref inconclusives, ref timeOuts, ref outOfMemories);
- switch (outcome) {
- default:
- Contract.Assert(false); // unexpected outcome
- throw new cce.UnreachableException();
- case VCGen.Outcome.ReachedBound:
- Inform(String.Format("{0}verified", timeIndication));
- Console.WriteLine(string.Format("Stratified Inlining: Reached recursion bound of {0}", CommandLineOptions.Clo.RecursionBound));
- verified++;
- break;
- case VCGen.Outcome.Correct:
- if (CommandLineOptions.Clo.vcVariety == CommandLineOptions.VCVariety.Doomed) {
- Inform(String.Format("{0}credible", timeIndication));
- verified++;
- } else {
- Inform(String.Format("{0}verified", timeIndication));
- verified++;
- }
- break;
- case VCGen.Outcome.TimedOut:
- timeOuts++;
- Inform(String.Format("{0}timed out", timeIndication));
- break;
- case VCGen.Outcome.OutOfMemory:
- outOfMemories++;
- Inform(String.Format("{0}out of memory", timeIndication));
- break;
- case VCGen.Outcome.Inconclusive:
- inconclusives++;
- Inform(String.Format("{0}inconclusive", timeIndication));
- break;
- case VCGen.Outcome.Errors:
- if (CommandLineOptions.Clo.vcVariety == CommandLineOptions.VCVariety.Doomed) {
- Inform(String.Format("{0}doomed", timeIndication));
- errorCount++;
- } //else {
- Contract.Assert(errors != null); // guaranteed by postcondition of VerifyImplementation
-
- {
- // BP1xxx: Parsing errors
- // BP2xxx: Name resolution errors
- // BP3xxx: Typechecking errors
- // BP4xxx: Abstract interpretation errors (Is there such a thing?)
- // BP5xxx: Verification errors
-
- if (CommandLineOptions.Clo.ExtractLoops && (vcgen is VCGen))
- {
- for (int i = 0; i < errors.Count; i++)
- {
- errors[i] = (vcgen as VCGen).extractLoopTrace(errors[i], impl.Name, program, extractLoopMappingInfo);
- }
- }
-
- errors.Sort(new CounterexampleComparer());
- foreach (Counterexample error in errors) {
- if (error is CallCounterexample) {
- CallCounterexample err = (CallCounterexample)error;
- if (!CommandLineOptions.Clo.ForceBplErrors && err.FailingRequires.ErrorMessage != null) {
- ReportBplError(err.FailingRequires, err.FailingRequires.ErrorMessage, true, false);
- } else {
- ReportBplError(err.FailingCall, "Error BP5002: A precondition for this call might not hold.", true, true);
- ReportBplError(err.FailingRequires, "Related location: This is the precondition that might not hold.", false, true);
- }
- if (CommandLineOptions.Clo.XmlSink != null) {
- CommandLineOptions.Clo.XmlSink.WriteError("precondition violation", err.FailingCall.tok, err.FailingRequires.tok, error.Trace);
- }
- } else if (error is ReturnCounterexample) {
- ReturnCounterexample err = (ReturnCounterexample)error;
- if (!CommandLineOptions.Clo.ForceBplErrors && err.FailingEnsures.ErrorMessage != null) {
- ReportBplError(err.FailingEnsures, err.FailingEnsures.ErrorMessage, true, false);
- } else {
- ReportBplError(err.FailingReturn, "Error BP5003: A postcondition might not hold on this return path.", true, true);
- ReportBplError(err.FailingEnsures, "Related location: This is the postcondition that might not hold.", false, true);
- }
- if (CommandLineOptions.Clo.XmlSink != null) {
- CommandLineOptions.Clo.XmlSink.WriteError("postcondition violation", err.FailingReturn.tok, err.FailingEnsures.tok, error.Trace);
- }
- } else // error is AssertCounterexample
- {
- AssertCounterexample err = (AssertCounterexample)error;
- if (err.FailingAssert is LoopInitAssertCmd) {
- ReportBplError(err.FailingAssert, "Error BP5004: This loop invariant might not hold on entry.", true, true);
- if (CommandLineOptions.Clo.XmlSink != null) {
- CommandLineOptions.Clo.XmlSink.WriteError("loop invariant entry violation", err.FailingAssert.tok, null, error.Trace);
- }
- } else if (err.FailingAssert is LoopInvMaintainedAssertCmd) {
- // this assertion is a loop invariant which is not maintained
- ReportBplError(err.FailingAssert, "Error BP5005: This loop invariant might not be maintained by the loop.", true, true);
- if (CommandLineOptions.Clo.XmlSink != null) {
- CommandLineOptions.Clo.XmlSink.WriteError("loop invariant maintenance violation", err.FailingAssert.tok, null, error.Trace);
- }
- } else {
- if (!CommandLineOptions.Clo.ForceBplErrors && err.FailingAssert.ErrorMessage != null) {
- ReportBplError(err.FailingAssert, err.FailingAssert.ErrorMessage, true, false);
- } else if (err.FailingAssert.ErrorData is string) {
- ReportBplError(err.FailingAssert, (string)err.FailingAssert.ErrorData, true, true);
- } else {
- ReportBplError(err.FailingAssert, "Error BP5001: This assertion might not hold.", true, true);
- }
- if (CommandLineOptions.Clo.XmlSink != null) {
- CommandLineOptions.Clo.XmlSink.WriteError("assertion violation", err.FailingAssert.tok, null, error.Trace);
- }
- }
- }
- if (CommandLineOptions.Clo.EnhancedErrorMessages == 1) {
- foreach (string info in error.relatedInformation) {
- Contract.Assert(info != null);
- Console.WriteLine(" " + info);
- }
- }
- if (CommandLineOptions.Clo.ErrorTrace > 0) {
- Console.WriteLine("Execution trace:");
- error.Print(4);
- }
- if (CommandLineOptions.Clo.ModelViewFile != null) {
- error.PrintModel();
- }
- errorCount++;
- }
- //}
- Inform(String.Format("{0}error{1}", timeIndication, errors.Count == 1 ? "" : "s"));
- }
- break;
- }
if (CommandLineOptions.Clo.XmlSink != null) {
CommandLineOptions.Clo.XmlSink.WriteEndMethod(outcome.ToString().ToLowerInvariant(), end, elapsed);
}
@@ -730,6 +736,7 @@ namespace Microsoft.Boogie {
}
}
}
+
vcgen.Close();
cce.NonNull(CommandLineOptions.Clo.TheProverFactory).Close();
@@ -738,6 +745,5 @@ namespace Microsoft.Boogie {
return PipelineOutcome.VerificationCompleted;
}
-
}
}
diff --git a/Source/BoogieDriver/BoogieDriver.csproj b/Source/BoogieDriver/BoogieDriver.csproj
index 52714dc9..9b6e329b 100644
--- a/Source/BoogieDriver/BoogieDriver.csproj
+++ b/Source/BoogieDriver/BoogieDriver.csproj
@@ -184,22 +184,10 @@
<Project>{435D5BD0-6F62-49F8-BB24-33E2257519AD}</Project>
<Name>Isabelle</Name>
</ProjectReference>
- <ProjectReference Include="..\Provers\Simplify\Simplify.csproj">
- <Project>{FEE9F01B-9722-4A76-A24B-72A4016DFA8E}</Project>
- <Name>Simplify</Name>
- </ProjectReference>
<ProjectReference Include="..\Provers\SMTLib\SMTLib.csproj">
<Project>{9B163AA3-36BC-4AFB-88AB-79BC9E97E401}</Project>
<Name>SMTLib</Name>
</ProjectReference>
- <ProjectReference Include="..\Provers\TPTP\TPTP.csproj">
- <Project>{A598ED5A-93AD-4125-A555-3921A2F936FA}</Project>
- <Name>TPTP</Name>
- </ProjectReference>
- <ProjectReference Include="..\Provers\Z3\Z3.csproj">
- <Project>{BB49B90B-BE21-4BE8-85BA-359FDB55F4DF}</Project>
- <Name>Z3</Name>
- </ProjectReference>
<ProjectReference Include="..\VCGeneration\VCGeneration.csproj">
<Project>{E1F10180-C7B9-4147-B51F-FA1B701966DC}</Project>
<Name>VCGeneration</Name>
diff --git a/Source/Core/CommandLineOptions.cs b/Source/Core/CommandLineOptions.cs
index e75fe867..1a2d7fda 100644
--- a/Source/Core/CommandLineOptions.cs
+++ b/Source/Core/CommandLineOptions.cs
@@ -389,6 +389,7 @@ namespace Microsoft.Boogie {
public int /*(0:3)*/ ErrorTrace = 1;
public bool IntraproceduralInfer = true;
public bool ContractInfer = false;
+ public bool PrintAssignment = false;
public int InlineDepth = -1;
public bool UseUncheckedContracts = false;
public bool SimplifyLogFileAppend = false;
@@ -830,10 +831,6 @@ namespace Microsoft.Boogie {
ps.GetNumericArgument(ref EnhancedErrorMessages, 2);
return true;
- case "contractInfer":
- ContractInfer = true;
- return true;
-
case "inlineDepth":
ps.GetNumericArgument(ref InlineDepth);
return true;
@@ -1007,7 +1004,11 @@ namespace Microsoft.Boogie {
}
}
return true;
-
+ case "siVerbose":
+ if (ps.ConfirmArgumentCount(1)) {
+ StratifiedInliningVerbose = Int32.Parse(cce.NonNull(args[ps.i]));
+ }
+ return true;
case "recursionBound":
if (ps.ConfirmArgumentCount(1)) {
RecursionBound = Int32.Parse(cce.NonNull(args[ps.i]));
@@ -1225,7 +1226,9 @@ namespace Microsoft.Boogie {
ps.CheckBooleanFlag("monomorphize", ref Monomorphize) ||
ps.CheckBooleanFlag("useArrayTheory", ref UseArrayTheory) ||
ps.CheckBooleanFlag("doModSetAnalysis", ref DoModSetAnalysis) ||
- ps.CheckBooleanFlag("doNotUseLabels", ref UseLabels, false)
+ ps.CheckBooleanFlag("doNotUseLabels", ref UseLabels, false) ||
+ ps.CheckBooleanFlag("contractInfer", ref ContractInfer) ||
+ ps.CheckBooleanFlag("printAssignment", ref PrintAssignment)
) {
// one of the boolean flags matched
return true;
diff --git a/Source/Dafny/Compiler.cs b/Source/Dafny/Compiler.cs
index a1f9e4fc..d5b15300 100644
--- a/Source/Dafny/Compiler.cs
+++ b/Source/Dafny/Compiler.cs
@@ -67,6 +67,10 @@ namespace Microsoft.Dafny {
CompileBuiltIns(program.BuiltIns);
foreach (ModuleDecl m in program.Modules) {
+ if (m.IsGhost) {
+ // the purpose of a ghost module is to skip compilation
+ continue;
+ }
int indent = 0;
if (!m.IsDefaultModule) {
wr.WriteLine("namespace @{0} {{", m.Name);
@@ -599,7 +603,7 @@ namespace Microsoft.Dafny {
return name + "]";
} else if (type is UserDefinedType) {
UserDefinedType udt = (UserDefinedType)type;
- string s = "@" + udt.Name;
+ string s = "@" + udt.FullName;
if (udt.TypeArgs.Count != 0) {
if (Contract.Exists(udt.TypeArgs, argType =>argType is ObjectType)) {
Error("compilation does not support type 'object' as a type parameter; consider introducing a ghost");
diff --git a/Source/Dafny/Dafny.atg b/Source/Dafny/Dafny.atg
index 3aa7f2d3..740926e5 100644
--- a/Source/Dafny/Dafny.atg
+++ b/Source/Dafny/Dafny.atg
@@ -148,27 +148,35 @@ Dafny
defaultModule = new DefaultModuleDecl();
}
IToken idRefined;
+ bool isGhost;
.)
- { "module" (. attrs = null; idRefined = null; theImports = new List<string/*!*/>();
- namedModuleDefaultClassMembers = new List<MemberDecl>();
- .)
- { Attribute<ref attrs> }
- Ident<out id> (. defaultModule.ImportNames.Add(id.val); .)
- [ "refines" Ident<out idRefined> ]
- [ "imports" Idents<theImports> ] (. module = new ModuleDecl(id, id.val, idRefined == null ? null : idRefined.val, theImports, attrs); .)
- "{" (. module.BodyStartTok = t; .)
- { ClassDecl<module, out c> (. module.TopLevelDecls.Add(c); .)
- | DatatypeDecl<module, out dt> (. module.TopLevelDecls.Add(dt); .)
- | ArbitraryTypeDecl<module, out at>(. module.TopLevelDecls.Add(at); .)
- | ClassMemberDecl<namedModuleDefaultClassMembers, false>
- }
- "}" (. module.BodyEndTok = t;
- module.TopLevelDecls.Add(new DefaultClassDecl(module, namedModuleDefaultClassMembers));
- theModules.Add(module); .)
- | ClassDecl<defaultModule, out c> (. defaultModule.TopLevelDecls.Add(c); .)
- | DatatypeDecl<defaultModule, out dt> (. defaultModule.TopLevelDecls.Add(dt); .)
- | ArbitraryTypeDecl<defaultModule, out at> (. defaultModule.TopLevelDecls.Add(at); .)
- | ClassMemberDecl<membersDefaultClass, false>
+ { (. isGhost = false; .)
+ [ "ghost" (. isGhost = true; .) ]
+
+ ( "module" (. attrs = null; idRefined = null; theImports = new List<string/*!*/>();
+ namedModuleDefaultClassMembers = new List<MemberDecl>();
+ .)
+ { Attribute<ref attrs> }
+ Ident<out id> (. defaultModule.ImportNames.Add(id.val); .)
+ [ "refines" Ident<out idRefined> ]
+ [ "imports" Idents<theImports> ] (. module = new ModuleDecl(id, id.val, isGhost, idRefined == null ? null : idRefined.val, theImports, attrs); .)
+ "{" (. module.BodyStartTok = t; .)
+ { ClassDecl<module, out c> (. module.TopLevelDecls.Add(c); .)
+ | DatatypeDecl<module, out dt> (. module.TopLevelDecls.Add(dt); .)
+ | ArbitraryTypeDecl<module, out at>(. module.TopLevelDecls.Add(at); .)
+ | ClassMemberDecl<namedModuleDefaultClassMembers, false, false>
+ }
+ "}" (. module.BodyEndTok = t;
+ module.TopLevelDecls.Add(new DefaultClassDecl(module, namedModuleDefaultClassMembers));
+ theModules.Add(module); .)
+ | (. if (isGhost) { SemErr(t, "a class is not allowed to be declared as 'ghost'"); } .)
+ ClassDecl<defaultModule, out c> (. defaultModule.TopLevelDecls.Add(c); .)
+ | (. if (isGhost) { SemErr(t, "a datatype is not allowed to be declared as 'ghost'"); } .)
+ DatatypeDecl<defaultModule, out dt> (. defaultModule.TopLevelDecls.Add(dt); .)
+ | (. if (isGhost) { SemErr(t, "a type is not allowed to be declared as 'ghost'"); } .)
+ ArbitraryTypeDecl<defaultModule, out at> (. defaultModule.TopLevelDecls.Add(at); .)
+ | ClassMemberDecl<membersDefaultClass, isGhost, false>
+ )
}
(. if (defaultModuleCreatedHere) {
defaultModule.TopLevelDecls.Add(new DefaultClassDecl(defaultModule, membersDefaultClass));
@@ -201,7 +209,7 @@ ClassDecl<ModuleDecl/*!*/ module, out ClassDecl/*!*/ c>
Ident<out id>
[ GenericParameters<typeArgs> ]
"{" (. bodyStart = t; .)
- { ClassMemberDecl<members, true>
+ { ClassMemberDecl<members, false, true>
}
"}"
(. c = new ClassDecl(id, id.val, module, typeArgs, members, attrs);
@@ -209,11 +217,12 @@ ClassDecl<ModuleDecl/*!*/ module, out ClassDecl/*!*/ c>
c.BodyEndTok = t;
.)
.
-ClassMemberDecl<.List<MemberDecl/*!*/>/*!*/ mm, bool allowConstructors.>
+ClassMemberDecl<.List<MemberDecl/*!*/>/*!*/ mm, bool isAlreadyGhost, bool allowConstructors.>
= (. Contract.Requires(cce.NonNullElements(mm));
Method/*!*/ m;
Function/*!*/ f;
MemberModifiers mmod = new MemberModifiers();
+ mmod.IsGhost = isAlreadyGhost;
.)
{ "ghost" (. mmod.IsGhost = true; .)
| "static" (. mmod.IsStatic = true; .)
@@ -365,7 +374,7 @@ MethodDecl<MemberModifiers mmod, bool allowConstructor, out Method/*!*/ m>
List<Expression/*!*/> dec = new List<Expression/*!*/>();
Attributes decAttrs = null;
Attributes modAttrs = null;
- Statement/*!*/ bb; BlockStmt body = null;
+ BlockStmt body = null;
bool isConstructor = false;
bool signatureOmitted = false;
IToken bodyStart = Token.NoToken;
@@ -401,7 +410,7 @@ MethodDecl<MemberModifiers mmod, bool allowConstructor, out Method/*!*/ m>
| "..." (. signatureOmitted = true; openParen = Token.NoToken; .)
)
{ MethodSpec<req, mod, ens, dec, ref decAttrs, ref modAttrs> }
- [ BlockStmt<out bb, out bodyStart, out bodyEnd> (. body = (BlockStmt)bb; .)
+ [ BlockStmt<out body, out bodyStart, out bodyEnd>
]
(. if (isConstructor) {
m = new Constructor(id, id.val, typeArgs, ins,
@@ -526,7 +535,7 @@ FunctionDecl<MemberModifiers mmod, out Function/*!*/ f>
List<Expression/*!*/> ens = new List<Expression/*!*/>();
List<FrameExpression/*!*/> reads = new List<FrameExpression/*!*/>();
List<Expression/*!*/> decreases = new List<Expression/*!*/>();
- Expression/*!*/ bb; Expression body = null;
+ Expression body = null;
bool isPredicate = false;
bool isFunctionMethod = false;
IToken openParen = null;
@@ -571,7 +580,7 @@ FunctionDecl<MemberModifiers mmod, out Function/*!*/ f>
)
{ FunctionSpec<reqs, reads, ens, decreases> }
- [ FunctionBody<out bb, out bodyStart, out bodyEnd> (. body = bb; .)
+ [ FunctionBody<out body, out bodyStart, out bodyEnd>
]
(. if (isPredicate) {
f = new Predicate(id, id.val, mmod.IsStatic, !isFunctionMethod, mmod.IsUnlimited, typeArgs, openParen, formals,
@@ -634,7 +643,7 @@ FunctionBody<out Expression/*!*/ e, out IToken bodyStart, out IToken bodyEnd>
"}" (. bodyEnd = t; .)
.
/*------------------------------------------------------------------------*/
-BlockStmt<out Statement/*!*/ block, out IToken bodyStart, out IToken bodyEnd>
+BlockStmt<out BlockStmt/*!*/ block, out IToken bodyStart, out IToken bodyEnd>
= (. Contract.Ensures(Contract.ValueAtReturn(out block) != null);
List<Statement/*!*/> body = new List<Statement/*!*/>();
.)
@@ -652,11 +661,12 @@ Stmt<.List<Statement/*!*/>/*!*/ ss.>
OneStmt<out Statement/*!*/ s>
= (. Contract.Ensures(Contract.ValueAtReturn(out s) != null); IToken/*!*/ x; IToken/*!*/ id; string label = null;
s = dummyStmt; /* to please the compiler */
+ BlockStmt bs;
IToken bodyStart, bodyEnd;
int breakCount;
.)
SYNC
- ( BlockStmt<out s, out bodyStart, out bodyEnd>
+ ( BlockStmt<out bs, out bodyStart, out bodyEnd> (. s = bs; .)
| AssertStmt<out s>
| AssumeStmt<out s>
| PrintStmt<out s>
@@ -793,7 +803,8 @@ VarDeclStatement<.out Statement/*!*/ s.>
IfStmt<out Statement/*!*/ ifStmt>
= (. Contract.Ensures(Contract.ValueAtReturn(out ifStmt) != null); IToken/*!*/ x;
Expression guard = null; bool guardOmitted = false;
- Statement/*!*/ thn;
+ BlockStmt/*!*/ thn;
+ BlockStmt/*!*/ bs;
Statement/*!*/ s;
Statement els = null;
IToken bodyStart, bodyEnd;
@@ -808,7 +819,7 @@ IfStmt<out Statement/*!*/ ifStmt>
BlockStmt<out thn, out bodyStart, out bodyEnd>
[ "else"
( IfStmt<out s> (. els = s; .)
- | BlockStmt<out s, out bodyStart, out bodyEnd> (. els = s; .)
+ | BlockStmt<out bs, out bodyStart, out bodyEnd> (. els = bs; .)
)
]
(. if (guardOmitted) {
@@ -846,7 +857,7 @@ WhileStmt<out Statement/*!*/ stmt>
Attributes decAttrs = null;
Attributes modAttrs = null;
List<FrameExpression/*!*/> mod = null;
- Statement/*!*/ body = null; bool bodyOmitted = false;
+ BlockStmt/*!*/ body = null; bool bodyOmitted = false;
IToken bodyStart = null, bodyEnd = null;
List<GuardedAlternative> alternatives;
stmt = dummyStmt; // to please the compiler
@@ -869,7 +880,7 @@ WhileStmt<out Statement/*!*/ stmt>
SemErr(mod[0].E.tok, "'modifies' clauses are not allowed on refining loops");
}
if (body == null) {
- body = new AssertStmt(x, new LiteralExpr(x, true), null);
+ body = new BlockStmt(x, new List<Statement>());
}
stmt = new WhileStmt(x, guard, invariants, new Specification<Expression>(null, null), new Specification<FrameExpression>(null, null), body);
stmt = new SkeletonStatement(stmt, guardOmitted, bodyOmitted);
@@ -1007,7 +1018,7 @@ ParallelStmt<out Statement/*!*/ s>
var ens = new List<MaybeFreeExpression/*!*/>();
bool isFree;
Expression/*!*/ e;
- Statement/*!*/ block;
+ BlockStmt/*!*/ block;
IToken bodyStart, bodyEnd;
.)
"parallel" (. x = t; .)
diff --git a/Source/Dafny/DafnyAst.cs b/Source/Dafny/DafnyAst.cs
index c9c0ec08..4eb50fa8 100644
--- a/Source/Dafny/DafnyAst.cs
+++ b/Source/Dafny/DafnyAst.cs
@@ -32,7 +32,7 @@ namespace Microsoft.Dafny {
public class BuiltIns
{
- public readonly ModuleDecl SystemModule = new ModuleDecl(Token.NoToken, "_System", null, new List<string>(), null);
+ public readonly ModuleDecl SystemModule = new ModuleDecl(Token.NoToken, "_System", false, null, new List<string>(), null);
Dictionary<int, ClassDecl/*!*/> arrayTypeDecls = new Dictionary<int, ClassDecl>();
public BuiltIns() {
@@ -111,6 +111,28 @@ namespace Microsoft.Dafny {
return false;
}
+ /// <summary>
+ /// Returns true if "nm" is a specified attribute. If it is, then:
+ /// - if the attribute is {:nm true}, then value==true
+ /// - if the attribute is {:nm false}, then value==false
+ /// - if the attribute is anything else, then value returns as whatever it was passed in as.
+ /// </summary>
+ public static bool ContainsBool(Attributes attrs, string nm, ref bool value) {
+ Contract.Requires(nm != null);
+ for (; attrs != null; attrs = attrs.Prev) {
+ if (attrs.Name == nm) {
+ if (attrs.Args.Count == 1) {
+ var arg = attrs.Args[0].E as LiteralExpr;
+ if (arg != null && arg.Value is bool) {
+ value = (bool)arg.Value;
+ }
+ }
+ return true;
+ }
+ }
+ return false;
+ }
+
public class Argument
{
public readonly IToken Tok;
@@ -325,6 +347,16 @@ namespace Microsoft.Dafny {
[Rep]
public readonly List<Type/*!*/>/*!*/ TypeArgs;
+ public string FullName {
+ get {
+ if (ResolvedClass != null) {
+ return ResolvedClass.Module.Name + "." + Name;
+ } else {
+ return Name;
+ }
+ }
+ }
+
public TopLevelDecl ResolvedClass; // filled in by resolution, if Name denotes a class/datatype and TypeArgs match the type parameters of that class/datatype
public TypeParameter ResolvedParam; // filled in by resolution, if Name denotes an enclosing type parameter and TypeArgs is the empty list
@@ -621,6 +653,7 @@ namespace Microsoft.Dafny {
public readonly List<TopLevelDecl/*!*/> TopLevelDecls = new List<TopLevelDecl/*!*/>(); // filled in by the parser; readonly after that
public readonly Graph<MemberDecl/*!*/> CallGraph = new Graph<MemberDecl/*!*/>(); // filled in during resolution
public int Height; // height in the topological sorting of modules; filled in during resolution
+ public readonly bool IsGhost;
[ContractInvariantMethod]
void ObjectInvariant() {
@@ -629,7 +662,7 @@ namespace Microsoft.Dafny {
Contract.Invariant(CallGraph != null);
}
- public ModuleDecl(IToken tok, string name, string refinementBase, [Captured] List<string/*!*/>/*!*/ imports, Attributes attributes)
+ public ModuleDecl(IToken tok, string name, bool isGhost, string refinementBase, [Captured] List<string/*!*/>/*!*/ imports, Attributes attributes)
: base(tok, name, attributes) {
Contract.Requires(tok != null);
Contract.Requires(name != null);
@@ -642,6 +675,7 @@ namespace Microsoft.Dafny {
ImportNames.Add(nm);
}
}
+ IsGhost = isGhost;
}
public virtual bool IsDefaultModule {
get {
@@ -651,7 +685,7 @@ namespace Microsoft.Dafny {
}
public class DefaultModuleDecl : ModuleDecl {
- public DefaultModuleDecl() : base(Token.NoToken, "_default", null, new List<string/*!*/>(), null) {
+ public DefaultModuleDecl() : base(Token.NoToken, "_default", false, null, new List<string/*!*/>(), null) {
}
public override bool IsDefaultModule {
get {
@@ -1066,7 +1100,7 @@ namespace Microsoft.Dafny {
public readonly List<FrameExpression/*!*/>/*!*/ Reads;
public readonly List<Expression/*!*/>/*!*/ Ens;
public readonly Specification<Expression>/*!*/ Decreases;
- public readonly Expression Body; // an extended expression
+ public Expression Body; // an extended expression; Body is readonly after construction, except for any kind of rewrite that may take place around the time of resolution
public readonly bool SignatureIsOmitted; // is "false" for all Function objects that survive into resolution
[ContractInvariantMethod]
void ObjectInvariant() {
@@ -1133,7 +1167,7 @@ namespace Microsoft.Dafny {
public readonly Specification<FrameExpression>/*!*/ Mod;
public readonly List<MaybeFreeExpression/*!*/>/*!*/ Ens;
public readonly Specification<Expression>/*!*/ Decreases;
- public readonly BlockStmt Body;
+ public BlockStmt Body; // Body is readonly after construction, except for any kind of rewrite that may take place around the time of resolution
[ContractInvariantMethod]
void ObjectInvariant() {
@@ -1238,6 +1272,13 @@ namespace Microsoft.Dafny {
Contract.Requires(tok != null);
this.Tok = tok;
}
+
+ /// <summary>
+ /// Returns the non-null substatements of the Statements.
+ /// </summary>
+ public virtual IEnumerable<Statement> SubStatements {
+ get { yield break; }
+ }
}
public class LabelNode
@@ -1512,6 +1553,10 @@ namespace Microsoft.Dafny {
public ConcreteSyntaxStatement(IToken tok)
: base(tok) {
}
+
+ public override IEnumerable<Statement> SubStatements {
+ get { return ResolvedStatements; }
+ }
}
public class VarDeclStmt : ConcreteSyntaxStatement
@@ -1584,6 +1629,15 @@ namespace Microsoft.Dafny {
this.Lhs = lhs;
this.Rhs = rhs;
}
+
+ public override IEnumerable<Statement> SubStatements {
+ get {
+ var trhs = Rhs as TypeRhs;
+ if (trhs != null && trhs.InitCall != null) {
+ yield return trhs.InitCall;
+ }
+ }
+ }
}
public class VarDecl : Statement, IVariable {
@@ -1684,20 +1738,23 @@ namespace Microsoft.Dafny {
Contract.Requires(tok != null);
Contract.Requires(cce.NonNullElements(body));
this.Body = body;
+ }
+ public override IEnumerable<Statement> SubStatements {
+ get { return Body; }
}
}
public class IfStmt : Statement {
public readonly Expression Guard;
- public readonly Statement Thn;
+ public readonly BlockStmt Thn;
public readonly Statement Els;
[ContractInvariantMethod]
void ObjectInvariant() {
Contract.Invariant(Thn != null);
Contract.Invariant(Els == null || Els is BlockStmt || Els is IfStmt);
}
- public IfStmt(IToken tok, Expression guard, Statement thn, Statement els)
+ public IfStmt(IToken tok, Expression guard, BlockStmt thn, Statement els)
: base(tok) {
Contract.Requires(tok != null);
Contract.Requires(thn != null);
@@ -1706,6 +1763,14 @@ namespace Microsoft.Dafny {
this.Thn = thn;
this.Els = els;
}
+ public override IEnumerable<Statement> SubStatements {
+ get {
+ yield return Thn;
+ if (Els != null) {
+ yield return Els;
+ }
+ }
+ }
}
public class GuardedAlternative
@@ -1743,6 +1808,15 @@ namespace Microsoft.Dafny {
Contract.Requires(alternatives != null);
this.Alternatives = alternatives;
}
+ public override IEnumerable<Statement> SubStatements {
+ get {
+ foreach (var alt in Alternatives) {
+ foreach (var s in alt.Body) {
+ yield return s;
+ }
+ }
+ }
+ }
}
public abstract class LoopStmt : Statement
@@ -1773,7 +1847,7 @@ namespace Microsoft.Dafny {
public class WhileStmt : LoopStmt
{
public readonly Expression Guard;
- public readonly Statement/*!*/ Body;
+ public readonly BlockStmt/*!*/ Body;
[ContractInvariantMethod]
void ObjectInvariant() {
Contract.Invariant(Body != null);
@@ -1781,13 +1855,19 @@ namespace Microsoft.Dafny {
public WhileStmt(IToken tok, Expression guard,
List<MaybeFreeExpression/*!*/>/*!*/ invariants, Specification<Expression>/*!*/ decreases, Specification<FrameExpression>/*!*/ mod,
- Statement/*!*/ body)
+ BlockStmt/*!*/ body)
: base(tok, invariants, decreases, mod) {
Contract.Requires(tok != null);
Contract.Requires(body != null);
this.Guard = guard;
this.Body = body;
}
+
+ public override IEnumerable<Statement> SubStatements {
+ get {
+ yield return Body;
+ }
+ }
}
public class AlternativeLoopStmt : LoopStmt
@@ -1805,6 +1885,15 @@ namespace Microsoft.Dafny {
Contract.Requires(alternatives != null);
this.Alternatives = alternatives;
}
+ public override IEnumerable<Statement> SubStatements {
+ get {
+ foreach (var alt in Alternatives) {
+ foreach (var s in alt.Body) {
+ yield return s;
+ }
+ }
+ }
+ }
}
public class ParallelStmt : Statement
@@ -1880,6 +1969,12 @@ namespace Microsoft.Dafny {
}
}
}
+
+ public override IEnumerable<Statement> SubStatements {
+ get {
+ yield return Body;
+ }
+ }
}
public class MatchStmt : Statement
@@ -1902,7 +1997,16 @@ namespace Microsoft.Dafny {
Contract.Requires(cce.NonNullElements(cases));
this.Source = source;
this.Cases = cases;
+ }
+ public override IEnumerable<Statement> SubStatements {
+ get {
+ foreach (var kase in Cases) {
+ foreach (var s in kase.Body) {
+ yield return s;
+ }
+ }
+ }
}
}
@@ -1958,6 +2062,19 @@ namespace Microsoft.Dafny {
ConditionOmitted = conditionOmitted;
BodyOmitted = bodyOmitted;
}
+ public override IEnumerable<Statement> SubStatements {
+ get {
+ // The SkeletonStatement is really a modification of its inner statement S. Therefore,
+ // we don't consider S to be a substatement. Instead, the substatements of S are the
+ // substatements of the SkeletonStatement. In the case the SkeletonStatement modifies
+ // S by omitting its body (which is true only for loops), there are no substatements.
+ if (!BodyOmitted) {
+ foreach (var s in S.SubStatements) {
+ yield return s;
+ }
+ }
+ }
+ }
}
// ------------------------------------------------------------------------------------------------------
@@ -2600,6 +2717,88 @@ namespace Microsoft.Dafny {
}
public ResolvedOpcode ResolvedOp; // filled in by resolution
+ public static Opcode ResolvedOp2SyntacticOp(ResolvedOpcode rop) {
+ switch (rop) {
+ case ResolvedOpcode.Iff: return Opcode.Iff;
+ case ResolvedOpcode.Imp: return Opcode.Imp;
+ case ResolvedOpcode.And: return Opcode.And;
+ case ResolvedOpcode.Or: return Opcode.Or;
+
+ case ResolvedOpcode.EqCommon:
+ case ResolvedOpcode.SetEq:
+ case ResolvedOpcode.MultiSetEq:
+ case ResolvedOpcode.SeqEq:
+ return Opcode.Eq;
+
+ case ResolvedOpcode.NeqCommon:
+ case ResolvedOpcode.SetNeq:
+ case ResolvedOpcode.MultiSetNeq:
+ case ResolvedOpcode.SeqNeq:
+ return Opcode.Neq;
+
+ case ResolvedOpcode.Lt:
+ case ResolvedOpcode.ProperSubset:
+ case ResolvedOpcode.ProperMultiSuperset:
+ case ResolvedOpcode.ProperPrefix:
+ case ResolvedOpcode.RankLt:
+ return Opcode.Lt;
+
+ case ResolvedOpcode.Le:
+ case ResolvedOpcode.Subset:
+ case ResolvedOpcode.MultiSubset:
+ case ResolvedOpcode.Prefix:
+ return Opcode.Le;
+
+ case ResolvedOpcode.Ge:
+ case ResolvedOpcode.Superset:
+ case ResolvedOpcode.MultiSuperset:
+ return Opcode.Ge;
+
+ case ResolvedOpcode.Gt:
+ case ResolvedOpcode.ProperSuperset:
+ case ResolvedOpcode.ProperMultiSubset:
+ case ResolvedOpcode.RankGt:
+ return Opcode.Gt;
+
+ case ResolvedOpcode.Add:
+ case ResolvedOpcode.Union:
+ case ResolvedOpcode.MultiSetUnion:
+ case ResolvedOpcode.Concat:
+ return Opcode.Add;
+
+ case ResolvedOpcode.Sub:
+ case ResolvedOpcode.SetDifference:
+ case ResolvedOpcode.MultiSetDifference:
+ return Opcode.Sub;
+
+ case ResolvedOpcode.Mul:
+ case ResolvedOpcode.Intersection:
+ case ResolvedOpcode.MultiSetIntersection:
+ return Opcode.Mul;
+
+ case ResolvedOpcode.Div: return Opcode.Div;
+ case ResolvedOpcode.Mod: return Opcode.Mod;
+
+ case ResolvedOpcode.Disjoint:
+ case ResolvedOpcode.MultiSetDisjoint:
+ return Opcode.Disjoint;
+
+ case ResolvedOpcode.InSet:
+ case ResolvedOpcode.InMultiSet:
+ case ResolvedOpcode.InSeq:
+ return Opcode.In;
+
+ case ResolvedOpcode.NotInSet:
+ case ResolvedOpcode.NotInMultiSet:
+ case ResolvedOpcode.NotInSeq:
+ return Opcode.NotIn;
+
+ default:
+ Contract.Assert(false); // unexpected ResolvedOpcode
+ return Opcode.Add; // please compiler
+ }
+ }
+
public static string OpcodeString(Opcode op) {
Contract.Ensures(Contract.Result<string>() != null);
diff --git a/Source/Dafny/DafnyPipeline.csproj b/Source/Dafny/DafnyPipeline.csproj
index 7264389b..cf2b51eb 100644
--- a/Source/Dafny/DafnyPipeline.csproj
+++ b/Source/Dafny/DafnyPipeline.csproj
@@ -158,6 +158,7 @@
<Compile Include="Printer.cs" />
<Compile Include="RefinementTransformer.cs" />
<Compile Include="Resolver.cs" />
+ <Compile Include="Rewriter.cs" />
<Compile Include="SccGraph.cs" />
<Compile Include="Translator.cs" />
<Compile Include="..\version.cs" />
diff --git a/Source/Dafny/Parser.cs b/Source/Dafny/Parser.cs
index 7de10ac7..bf7d1fe1 100644
--- a/Source/Dafny/Parser.cs
+++ b/Source/Dafny/Parser.cs
@@ -198,10 +198,16 @@ bool IsAttribute() {
defaultModule = new DefaultModuleDecl();
}
IToken idRefined;
+ bool isGhost;
while (StartOf(1)) {
+ isGhost = false;
if (la.kind == 8) {
Get();
+ isGhost = true;
+ }
+ if (la.kind == 9) {
+ Get();
attrs = null; idRefined = null; theImports = new List<string/*!*/>();
namedModuleDefaultClassMembers = new List<MemberDecl>();
@@ -210,19 +216,19 @@ bool IsAttribute() {
}
Ident(out id);
defaultModule.ImportNames.Add(id.val);
- if (la.kind == 9) {
+ if (la.kind == 10) {
Get();
Ident(out idRefined);
}
- if (la.kind == 10) {
+ if (la.kind == 11) {
Get();
Idents(theImports);
}
- module = new ModuleDecl(id, id.val, idRefined == null ? null : idRefined.val, theImports, attrs);
+ module = new ModuleDecl(id, id.val, isGhost, idRefined == null ? null : idRefined.val, theImports, attrs);
Expect(6);
module.BodyStartTok = t;
while (StartOf(2)) {
- if (la.kind == 11) {
+ if (la.kind == 12) {
ClassDecl(module, out c);
module.TopLevelDecls.Add(c);
} else if (la.kind == 15) {
@@ -232,25 +238,28 @@ bool IsAttribute() {
ArbitraryTypeDecl(module, out at);
module.TopLevelDecls.Add(at);
} else {
- ClassMemberDecl(namedModuleDefaultClassMembers, false);
+ ClassMemberDecl(namedModuleDefaultClassMembers, false, false);
}
}
Expect(7);
module.BodyEndTok = t;
module.TopLevelDecls.Add(new DefaultClassDecl(module, namedModuleDefaultClassMembers));
theModules.Add(module);
- } else if (la.kind == 11) {
+ } else if (la.kind == 12) {
+ if (isGhost) { SemErr(t, "a class is not allowed to be declared as 'ghost'"); }
ClassDecl(defaultModule, out c);
defaultModule.TopLevelDecls.Add(c);
} else if (la.kind == 15) {
+ if (isGhost) { SemErr(t, "a datatype is not allowed to be declared as 'ghost'"); }
DatatypeDecl(defaultModule, out dt);
defaultModule.TopLevelDecls.Add(dt);
} else if (la.kind == 21) {
+ if (isGhost) { SemErr(t, "a type is not allowed to be declared as 'ghost'"); }
ArbitraryTypeDecl(defaultModule, out at);
defaultModule.TopLevelDecls.Add(at);
- } else {
- ClassMemberDecl(membersDefaultClass, false);
- }
+ } else if (StartOf(3)) {
+ ClassMemberDecl(membersDefaultClass, isGhost, false);
+ } else SynErr(106);
}
if (defaultModuleCreatedHere) {
defaultModule.TopLevelDecls.Add(new DefaultClassDecl(defaultModule, membersDefaultClass));
@@ -301,8 +310,8 @@ bool IsAttribute() {
List<MemberDecl/*!*/> members = new List<MemberDecl/*!*/>();
IToken bodyStart;
- while (!(la.kind == 0 || la.kind == 11)) {SynErr(106); Get();}
- Expect(11);
+ while (!(la.kind == 0 || la.kind == 12)) {SynErr(107); Get();}
+ Expect(12);
while (la.kind == 6) {
Attribute(ref attrs);
}
@@ -313,7 +322,7 @@ bool IsAttribute() {
Expect(6);
bodyStart = t;
while (StartOf(3)) {
- ClassMemberDecl(members, true);
+ ClassMemberDecl(members, false, true);
}
Expect(7);
c = new ClassDecl(id, id.val, module, typeArgs, members, attrs);
@@ -331,7 +340,7 @@ bool IsAttribute() {
List<DatatypeCtor/*!*/> ctors = new List<DatatypeCtor/*!*/>();
IToken bodyStart = Token.NoToken; // dummy assignment
- while (!(la.kind == 0 || la.kind == 15)) {SynErr(107); Get();}
+ while (!(la.kind == 0 || la.kind == 15)) {SynErr(108); Get();}
Expect(15);
while (la.kind == 6) {
Attribute(ref attrs);
@@ -347,7 +356,7 @@ bool IsAttribute() {
Get();
DatatypeMemberDecl(ctors);
}
- while (!(la.kind == 0 || la.kind == 18)) {SynErr(108); Get();}
+ while (!(la.kind == 0 || la.kind == 18)) {SynErr(109); Get();}
Expect(18);
dt = new DatatypeDecl(id, id.val, module, typeArgs, ctors, attrs);
dt.BodyStartTok = bodyStart;
@@ -365,18 +374,19 @@ bool IsAttribute() {
}
Ident(out id);
at = new ArbitraryTypeDecl(id, id.val, module, attrs);
- while (!(la.kind == 0 || la.kind == 18)) {SynErr(109); Get();}
+ while (!(la.kind == 0 || la.kind == 18)) {SynErr(110); Get();}
Expect(18);
}
- void ClassMemberDecl(List<MemberDecl/*!*/>/*!*/ mm, bool allowConstructors) {
+ void ClassMemberDecl(List<MemberDecl/*!*/>/*!*/ mm, bool isAlreadyGhost, bool allowConstructors) {
Contract.Requires(cce.NonNullElements(mm));
Method/*!*/ m;
Function/*!*/ f;
MemberModifiers mmod = new MemberModifiers();
+ mmod.IsGhost = isAlreadyGhost;
- while (la.kind == 12 || la.kind == 13 || la.kind == 14) {
- if (la.kind == 12) {
+ while (la.kind == 8 || la.kind == 13 || la.kind == 14) {
+ if (la.kind == 8) {
Get();
mmod.IsGhost = true;
} else if (la.kind == 13) {
@@ -395,7 +405,7 @@ bool IsAttribute() {
} else if (la.kind == 24 || la.kind == 25) {
MethodDecl(mmod, allowConstructors, out m);
mm.Add(m);
- } else SynErr(110);
+ } else SynErr(111);
}
void GenericParameters(List<TypeParameter/*!*/>/*!*/ typeArgs) {
@@ -417,7 +427,7 @@ bool IsAttribute() {
Attributes attrs = null;
IToken/*!*/ id; Type/*!*/ ty;
- while (!(la.kind == 0 || la.kind == 19)) {SynErr(111); Get();}
+ while (!(la.kind == 0 || la.kind == 19)) {SynErr(112); Get();}
Expect(19);
if (mmod.IsUnlimited) { SemErr(t, "fields cannot be declared 'unlimited'"); }
if (mmod.IsStatic) { SemErr(t, "fields cannot be declared 'static'"); }
@@ -432,7 +442,7 @@ bool IsAttribute() {
IdentType(out id, out ty);
mm.Add(new Field(id, id.val, mmod.IsGhost, ty, attrs));
}
- while (!(la.kind == 0 || la.kind == 18)) {SynErr(112); Get();}
+ while (!(la.kind == 0 || la.kind == 18)) {SynErr(113); Get();}
Expect(18);
}
@@ -447,7 +457,7 @@ bool IsAttribute() {
List<Expression/*!*/> ens = new List<Expression/*!*/>();
List<FrameExpression/*!*/> reads = new List<FrameExpression/*!*/>();
List<Expression/*!*/> decreases = new List<Expression/*!*/>();
- Expression/*!*/ bb; Expression body = null;
+ Expression body = null;
bool isPredicate = false;
bool isFunctionMethod = false;
IToken openParen = null;
@@ -478,7 +488,7 @@ bool IsAttribute() {
Get();
signatureOmitted = true;
openParen = Token.NoToken;
- } else SynErr(113);
+ } else SynErr(114);
} else if (la.kind == 43) {
Get();
isPredicate = true;
@@ -507,14 +517,13 @@ bool IsAttribute() {
Get();
signatureOmitted = true;
openParen = Token.NoToken;
- } else SynErr(114);
- } else SynErr(115);
+ } else SynErr(115);
+ } else SynErr(116);
while (StartOf(5)) {
FunctionSpec(reqs, reads, ens, decreases);
}
if (la.kind == 6) {
- FunctionBody(out bb, out bodyStart, out bodyEnd);
- body = bb;
+ FunctionBody(out body, out bodyStart, out bodyEnd);
}
if (isPredicate) {
f = new Predicate(id, id.val, mmod.IsStatic, !isFunctionMethod, mmod.IsUnlimited, typeArgs, openParen, formals,
@@ -542,13 +551,13 @@ bool IsAttribute() {
List<Expression/*!*/> dec = new List<Expression/*!*/>();
Attributes decAttrs = null;
Attributes modAttrs = null;
- Statement/*!*/ bb; BlockStmt body = null;
+ BlockStmt body = null;
bool isConstructor = false;
bool signatureOmitted = false;
IToken bodyStart = Token.NoToken;
IToken bodyEnd = Token.NoToken;
- while (!(la.kind == 0 || la.kind == 24 || la.kind == 25)) {SynErr(116); Get();}
+ while (!(la.kind == 0 || la.kind == 24 || la.kind == 25)) {SynErr(117); Get();}
if (la.kind == 24) {
Get();
} else if (la.kind == 25) {
@@ -559,7 +568,7 @@ bool IsAttribute() {
SemErr(t, "constructors are only allowed in classes");
}
- } else SynErr(117);
+ } else SynErr(118);
if (mmod.IsUnlimited) { SemErr(t, "methods cannot be declared 'unlimited'"); }
if (isConstructor) {
if (mmod.IsGhost) {
@@ -587,13 +596,12 @@ bool IsAttribute() {
} else if (la.kind == 27) {
Get();
signatureOmitted = true; openParen = Token.NoToken;
- } else SynErr(118);
+ } else SynErr(119);
while (StartOf(6)) {
MethodSpec(req, mod, ens, dec, ref decAttrs, ref modAttrs);
}
if (la.kind == 6) {
- BlockStmt(out bb, out bodyStart, out bodyEnd);
- body = (BlockStmt)bb;
+ BlockStmt(out body, out bodyStart, out bodyEnd);
}
if (isConstructor) {
m = new Constructor(id, id.val, typeArgs, ins,
@@ -649,7 +657,7 @@ bool IsAttribute() {
Contract.Ensures(Contract.ValueAtReturn(out id)!=null);
Contract.Ensures(Contract.ValueAtReturn(out ty)!=null);
isGhost = false;
- if (la.kind == 12) {
+ if (la.kind == 8) {
Get();
if (allowGhostKeyword) { isGhost = true; } else { SemErr(t, "formal cannot be declared 'ghost' in this context"); }
}
@@ -690,7 +698,7 @@ bool IsAttribute() {
Contract.Ensures(Contract.ValueAtReturn(out ty)!=null);
Contract.Ensures(Contract.ValueAtReturn(out identName)!=null);
string name = null; isGhost = false;
- if (la.kind == 12) {
+ if (la.kind == 8) {
Get();
isGhost = true;
}
@@ -771,7 +779,7 @@ bool IsAttribute() {
ReferenceType(out tok, out ty);
break;
}
- default: SynErr(119); break;
+ default: SynErr(120); break;
}
}
@@ -779,7 +787,7 @@ bool IsAttribute() {
Contract.Requires(cce.NonNullElements(formals)); IToken/*!*/ id; Type/*!*/ ty; bool isGhost;
Expect(33);
openParen = t;
- if (la.kind == 1 || la.kind == 12) {
+ if (la.kind == 1 || la.kind == 8) {
GIdentType(allowGhostKeyword, out id, out ty, out isGhost);
formals.Add(new Formal(id, id.val, ty, incoming, isGhost));
while (la.kind == 20) {
@@ -796,7 +804,7 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
Contract.Requires(cce.NonNullElements(req)); Contract.Requires(cce.NonNullElements(mod)); Contract.Requires(cce.NonNullElements(ens)); Contract.Requires(cce.NonNullElements(decreases));
Expression/*!*/ e; FrameExpression/*!*/ fe; bool isFree = false; Attributes ensAttrs = null;
- while (!(StartOf(8))) {SynErr(120); Get();}
+ while (!(StartOf(8))) {SynErr(121); Get();}
if (la.kind == 28) {
Get();
while (IsAttribute()) {
@@ -811,7 +819,7 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
mod.Add(fe);
}
}
- while (!(la.kind == 0 || la.kind == 18)) {SynErr(121); Get();}
+ while (!(la.kind == 0 || la.kind == 18)) {SynErr(122); Get();}
Expect(18);
} else if (la.kind == 29 || la.kind == 30 || la.kind == 31) {
if (la.kind == 29) {
@@ -821,7 +829,7 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
if (la.kind == 30) {
Get();
Expression(out e);
- while (!(la.kind == 0 || la.kind == 18)) {SynErr(122); Get();}
+ while (!(la.kind == 0 || la.kind == 18)) {SynErr(123); Get();}
Expect(18);
req.Add(new MaybeFreeExpression(e, isFree));
} else if (la.kind == 31) {
@@ -830,22 +838,22 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
Attribute(ref ensAttrs);
}
Expression(out e);
- while (!(la.kind == 0 || la.kind == 18)) {SynErr(123); Get();}
+ while (!(la.kind == 0 || la.kind == 18)) {SynErr(124); Get();}
Expect(18);
ens.Add(new MaybeFreeExpression(e, isFree, ensAttrs));
- } else SynErr(124);
+ } else SynErr(125);
} else if (la.kind == 32) {
Get();
while (IsAttribute()) {
Attribute(ref decAttrs);
}
DecreasesList(decreases, false);
- while (!(la.kind == 0 || la.kind == 18)) {SynErr(125); Get();}
+ while (!(la.kind == 0 || la.kind == 18)) {SynErr(126); Get();}
Expect(18);
- } else SynErr(126);
+ } else SynErr(127);
}
- void BlockStmt(out Statement/*!*/ block, out IToken bodyStart, out IToken bodyEnd) {
+ void BlockStmt(out BlockStmt/*!*/ block, out IToken bodyStart, out IToken bodyEnd) {
Contract.Ensures(Contract.ValueAtReturn(out block) != null);
List<Statement/*!*/> body = new List<Statement/*!*/>();
@@ -936,17 +944,17 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
GenericInstantiation(gt);
}
ty = new UserDefinedType(tok, tok.val, gt);
- } else SynErr(127);
+ } else SynErr(128);
}
void FunctionSpec(List<Expression/*!*/>/*!*/ reqs, List<FrameExpression/*!*/>/*!*/ reads, List<Expression/*!*/>/*!*/ ens, List<Expression/*!*/>/*!*/ decreases) {
Contract.Requires(cce.NonNullElements(reqs)); Contract.Requires(cce.NonNullElements(reads)); Contract.Requires(cce.NonNullElements(decreases));
Expression/*!*/ e; FrameExpression/*!*/ fe;
if (la.kind == 30) {
- while (!(la.kind == 0 || la.kind == 30)) {SynErr(128); Get();}
+ while (!(la.kind == 0 || la.kind == 30)) {SynErr(129); Get();}
Get();
Expression(out e);
- while (!(la.kind == 0 || la.kind == 18)) {SynErr(129); Get();}
+ while (!(la.kind == 0 || la.kind == 18)) {SynErr(130); Get();}
Expect(18);
reqs.Add(e);
} else if (la.kind == 44) {
@@ -960,20 +968,20 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
reads.Add(fe);
}
}
- while (!(la.kind == 0 || la.kind == 18)) {SynErr(130); Get();}
+ while (!(la.kind == 0 || la.kind == 18)) {SynErr(131); Get();}
Expect(18);
} else if (la.kind == 31) {
Get();
Expression(out e);
- while (!(la.kind == 0 || la.kind == 18)) {SynErr(131); Get();}
+ while (!(la.kind == 0 || la.kind == 18)) {SynErr(132); Get();}
Expect(18);
ens.Add(e);
} else if (la.kind == 32) {
Get();
DecreasesList(decreases, false);
- while (!(la.kind == 0 || la.kind == 18)) {SynErr(132); Get();}
+ while (!(la.kind == 0 || la.kind == 18)) {SynErr(133); Get();}
Expect(18);
- } else SynErr(133);
+ } else SynErr(134);
}
void FunctionBody(out Expression/*!*/ e, out IToken bodyStart, out IToken bodyEnd) {
@@ -992,7 +1000,7 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
fe = new FrameExpression(new WildcardExpr(t), null);
} else if (StartOf(9)) {
FrameExpression(out fe);
- } else SynErr(134);
+ } else SynErr(135);
}
void PossiblyWildExpression(out Expression/*!*/ e) {
@@ -1003,7 +1011,7 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
e = new WildcardExpr(t);
} else if (StartOf(9)) {
Expression(out e);
- } else SynErr(135);
+ } else SynErr(136);
}
void Stmt(List<Statement/*!*/>/*!*/ ss) {
@@ -1016,13 +1024,15 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
void OneStmt(out Statement/*!*/ s) {
Contract.Ensures(Contract.ValueAtReturn(out s) != null); IToken/*!*/ x; IToken/*!*/ id; string label = null;
s = dummyStmt; /* to please the compiler */
+ BlockStmt bs;
IToken bodyStart, bodyEnd;
int breakCount;
- while (!(StartOf(12))) {SynErr(136); Get();}
+ while (!(StartOf(12))) {SynErr(137); Get();}
switch (la.kind) {
case 6: {
- BlockStmt(out s, out bodyStart, out bodyEnd);
+ BlockStmt(out bs, out bodyStart, out bodyEnd);
+ s = bs;
break;
}
case 63: {
@@ -1041,7 +1051,7 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
UpdateStmt(out s);
break;
}
- case 12: case 19: {
+ case 8: case 19: {
VarDeclStatement(out s);
break;
}
@@ -1081,8 +1091,8 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
Get();
breakCount++;
}
- } else SynErr(137);
- while (!(la.kind == 0 || la.kind == 18)) {SynErr(138); Get();}
+ } else SynErr(138);
+ while (!(la.kind == 0 || la.kind == 18)) {SynErr(139); Get();}
Expect(18);
s = label != null ? new BreakStmt(x, label) : new BreakStmt(x, breakCount);
break;
@@ -1097,7 +1107,7 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
Expect(18);
break;
}
- default: SynErr(139); break;
+ default: SynErr(140); break;
}
}
@@ -1114,7 +1124,7 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
Expression(out e);
} else if (la.kind == 27) {
Get();
- } else SynErr(140);
+ } else SynErr(141);
Expect(18);
if (e == null) {
s = new SkeletonStatement(new AssertStmt(x, new LiteralExpr(x, true), attrs), true, false);
@@ -1186,7 +1196,7 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
} else if (la.kind == 5) {
Get();
SemErr(t, "invalid statement (did you forget the 'label' keyword?)");
- } else SynErr(141);
+ } else SynErr(142);
s = new UpdateStmt(x, lhss, rhss);
}
@@ -1197,7 +1207,7 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
List<VarDecl> lhss = new List<VarDecl>();
List<AssignmentRhs> rhss = new List<AssignmentRhs>();
- if (la.kind == 12) {
+ if (la.kind == 8) {
Get();
isGhost = true; x = t;
}
@@ -1242,7 +1252,8 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
void IfStmt(out Statement/*!*/ ifStmt) {
Contract.Ensures(Contract.ValueAtReturn(out ifStmt) != null); IToken/*!*/ x;
Expression guard = null; bool guardOmitted = false;
- Statement/*!*/ thn;
+ BlockStmt/*!*/ thn;
+ BlockStmt/*!*/ bs;
Statement/*!*/ s;
Statement els = null;
IToken bodyStart, bodyEnd;
@@ -1265,9 +1276,9 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
IfStmt(out s);
els = s;
} else if (la.kind == 6) {
- BlockStmt(out s, out bodyStart, out bodyEnd);
- els = s;
- } else SynErr(142);
+ BlockStmt(out bs, out bodyStart, out bodyEnd);
+ els = bs;
+ } else SynErr(143);
}
if (guardOmitted) {
ifStmt = new SkeletonStatement(new IfStmt(x, guard, thn, els), true, false);
@@ -1278,7 +1289,7 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
} else if (la.kind == 6) {
AlternativeBlock(out alternatives);
ifStmt = new AlternativeStmt(x, alternatives);
- } else SynErr(143);
+ } else SynErr(144);
}
void WhileStmt(out Statement/*!*/ stmt) {
@@ -1289,7 +1300,7 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
Attributes decAttrs = null;
Attributes modAttrs = null;
List<FrameExpression/*!*/> mod = null;
- Statement/*!*/ body = null; bool bodyOmitted = false;
+ BlockStmt/*!*/ body = null; bool bodyOmitted = false;
IToken bodyStart = null, bodyEnd = null;
List<GuardedAlternative> alternatives;
stmt = dummyStmt; // to please the compiler
@@ -1310,7 +1321,7 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
} else if (la.kind == 27) {
Get();
bodyOmitted = true;
- } else SynErr(144);
+ } else SynErr(145);
if (guardOmitted || bodyOmitted) {
if (decreases.Count != 0) {
SemErr(decreases[0].tok, "'decreases' clauses are not allowed on refining loops");
@@ -1319,7 +1330,7 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
SemErr(mod[0].E.tok, "'modifies' clauses are not allowed on refining loops");
}
if (body == null) {
- body = new AssertStmt(x, new LiteralExpr(x, true), null);
+ body = new BlockStmt(x, new List<Statement>());
}
stmt = new WhileStmt(x, guard, invariants, new Specification<Expression>(null, null), new Specification<FrameExpression>(null, null), body);
stmt = new SkeletonStatement(stmt, guardOmitted, bodyOmitted);
@@ -1331,7 +1342,7 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
LoopSpec(out invariants, out decreases, out mod, ref decAttrs, ref modAttrs);
AlternativeBlock(out alternatives);
stmt = new AlternativeLoopStmt(x, invariants, new Specification<Expression>(decreases, decAttrs), new Specification<FrameExpression>(mod, modAttrs), alternatives);
- } else SynErr(145);
+ } else SynErr(146);
}
void MatchStmt(out Statement/*!*/ s) {
@@ -1359,7 +1370,7 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
var ens = new List<MaybeFreeExpression/*!*/>();
bool isFree;
Expression/*!*/ e;
- Statement/*!*/ block;
+ BlockStmt/*!*/ block;
IToken bodyStart, bodyEnd;
Expect(66);
@@ -1461,7 +1472,7 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
} else if (StartOf(9)) {
Expression(out e);
r = new ExprRhs(e);
- } else SynErr(146);
+ } else SynErr(147);
while (la.kind == 6) {
Attribute(ref attrs);
}
@@ -1482,7 +1493,7 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
while (la.kind == 52 || la.kind == 54) {
Suffix(ref e);
}
- } else SynErr(147);
+ } else SynErr(148);
}
void Expressions(List<Expression/*!*/>/*!*/ args) {
@@ -1505,7 +1516,7 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
} else if (StartOf(9)) {
Expression(out ee);
e = ee;
- } else SynErr(148);
+ } else SynErr(149);
Expect(34);
}
@@ -1540,20 +1551,20 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
while (StartOf(16)) {
if (la.kind == 29 || la.kind == 61) {
Invariant(out invariant);
- while (!(la.kind == 0 || la.kind == 18)) {SynErr(149); Get();}
+ while (!(la.kind == 0 || la.kind == 18)) {SynErr(150); Get();}
Expect(18);
invariants.Add(invariant);
} else if (la.kind == 32) {
- while (!(la.kind == 0 || la.kind == 32)) {SynErr(150); Get();}
+ while (!(la.kind == 0 || la.kind == 32)) {SynErr(151); Get();}
Get();
while (IsAttribute()) {
Attribute(ref decAttrs);
}
DecreasesList(decreases, true);
- while (!(la.kind == 0 || la.kind == 18)) {SynErr(151); Get();}
+ while (!(la.kind == 0 || la.kind == 18)) {SynErr(152); Get();}
Expect(18);
} else {
- while (!(la.kind == 0 || la.kind == 28)) {SynErr(152); Get();}
+ while (!(la.kind == 0 || la.kind == 28)) {SynErr(153); Get();}
Get();
while (IsAttribute()) {
Attribute(ref modAttrs);
@@ -1568,7 +1579,7 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
mod.Add(fe);
}
}
- while (!(la.kind == 0 || la.kind == 18)) {SynErr(153); Get();}
+ while (!(la.kind == 0 || la.kind == 18)) {SynErr(154); Get();}
Expect(18);
}
}
@@ -1576,7 +1587,7 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
void Invariant(out MaybeFreeExpression/*!*/ invariant) {
bool isFree = false; Expression/*!*/ e; List<string> ids = new List<string>(); invariant = null; Attributes attrs = null;
- while (!(la.kind == 0 || la.kind == 29 || la.kind == 61)) {SynErr(154); Get();}
+ while (!(la.kind == 0 || la.kind == 29 || la.kind == 61)) {SynErr(155); Get();}
if (la.kind == 29) {
Get();
isFree = true;
@@ -1625,7 +1636,7 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
} else if (StartOf(9)) {
Expression(out e);
arg = new Attributes.Argument(t, e);
- } else SynErr(155);
+ } else SynErr(156);
}
void QuantifierDomain(out List<BoundVar/*!*/> bvars, out Attributes attrs, out Expression range) {
@@ -1677,7 +1688,7 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
Get();
} else if (la.kind == 68) {
Get();
- } else SynErr(156);
+ } else SynErr(157);
}
void LogicalExpression(out Expression/*!*/ e0) {
@@ -1715,7 +1726,7 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
Get();
} else if (la.kind == 70) {
Get();
- } else SynErr(157);
+ } else SynErr(158);
}
void RelationalExpression(out Expression/*!*/ e) {
@@ -1813,7 +1824,7 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
Get();
} else if (la.kind == 72) {
Get();
- } else SynErr(158);
+ } else SynErr(159);
}
void OrOp() {
@@ -1821,7 +1832,7 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
Get();
} else if (la.kind == 74) {
Get();
- } else SynErr(159);
+ } else SynErr(160);
}
void Term(out Expression/*!*/ e0) {
@@ -1913,7 +1924,7 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
x = t; op = BinaryExpr.Opcode.Ge;
break;
}
- default: SynErr(160); break;
+ default: SynErr(161); break;
}
}
@@ -1935,7 +1946,7 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
} else if (la.kind == 86) {
Get();
x = t; op = BinaryExpr.Opcode.Sub;
- } else SynErr(161);
+ } else SynErr(162);
}
void UnaryExpression(out Expression/*!*/ e) {
@@ -1981,7 +1992,7 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
}
break;
}
- default: SynErr(162); break;
+ default: SynErr(163); break;
}
}
@@ -1996,7 +2007,7 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
} else if (la.kind == 88) {
Get();
x = t; op = BinaryExpr.Opcode.Mod;
- } else SynErr(163);
+ } else SynErr(164);
}
void NegOp() {
@@ -2004,7 +2015,7 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
Get();
} else if (la.kind == 89) {
Get();
- } else SynErr(164);
+ } else SynErr(165);
}
void EndlessExpression(out Expression e) {
@@ -2081,7 +2092,7 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
e = new LetExpr(x, letVars, letRHSs, e);
break;
}
- default: SynErr(165); break;
+ default: SynErr(166); break;
}
}
@@ -2155,7 +2166,7 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
multipleIndices.Add(ee);
}
- } else SynErr(166);
+ } else SynErr(167);
} else if (la.kind == 98) {
Get();
anyDots = true;
@@ -2163,7 +2174,7 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
Expression(out ee);
e1 = ee;
}
- } else SynErr(167);
+ } else SynErr(168);
if (multipleIndices != null) {
e = new MultiSelectExpr(x, e, multipleIndices);
// make sure an array class with this dimensionality exists
@@ -2187,7 +2198,7 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
}
Expect(53);
- } else SynErr(168);
+ } else SynErr(169);
}
void DisplayExpr(out Expression e) {
@@ -2211,7 +2222,7 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
}
e = new SeqDisplayExpr(x, elements);
Expect(53);
- } else SynErr(169);
+ } else SynErr(170);
}
void MultiSetExpr(out Expression e) {
@@ -2237,7 +2248,7 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
Expect(34);
} else if (StartOf(19)) {
SemErr("multiset must be followed by multiset literal or expression to coerce in parentheses.");
- } else SynErr(170);
+ } else SynErr(171);
}
void ConstAtomExpression(out Expression/*!*/ e) {
@@ -2314,7 +2325,7 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
Expect(34);
break;
}
- default: SynErr(171); break;
+ default: SynErr(172); break;
}
}
@@ -2357,7 +2368,7 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
} else if (la.kind == 101 || la.kind == 102) {
Exists();
x = t;
- } else SynErr(172);
+ } else SynErr(173);
QuantifierDomain(out bvars, out attrs, out range);
QSep();
Expression(out body);
@@ -2427,7 +2438,7 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
Get();
} else if (la.kind == 100) {
Get();
- } else SynErr(173);
+ } else SynErr(174);
}
void Exists() {
@@ -2435,7 +2446,7 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
Get();
} else if (la.kind == 102) {
Get();
- } else SynErr(174);
+ } else SynErr(175);
}
void QSep() {
@@ -2443,7 +2454,7 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
Get();
} else if (la.kind == 104) {
Get();
- } else SynErr(175);
+ } else SynErr(176);
}
void AttributeBody(ref Attributes attrs) {
@@ -2479,19 +2490,19 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
}
static readonly bool[,]/*!*/ set = {
- {T,T,T,x, x,x,T,x, x,x,x,T, T,x,x,T, x,T,T,T, x,x,x,x, T,T,x,T, T,T,T,T, T,T,x,x, x,x,x,x, x,x,x,x, x,x,x,T, T,T,x,x, x,x,x,x, T,x,x,x, T,T,T,T, T,T,T,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,T,T, T,T,T,T, T,x,x,x, x,x,x,x, x,x,x},
- {x,x,x,x, x,x,x,x, T,x,x,T, T,T,T,T, x,x,x,T, x,T,x,x, T,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,T,T, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x},
- {x,x,x,x, x,x,x,x, x,x,x,T, T,T,T,T, x,x,x,T, x,T,x,x, T,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,T,T, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x},
- {x,x,x,x, x,x,x,x, x,x,x,x, T,T,T,x, x,x,x,T, x,x,x,x, T,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,T,T, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x},
- {T,x,x,x, x,x,T,T, T,x,x,T, T,T,T,T, x,x,x,T, x,T,T,x, T,T,x,x, x,x,T,T, T,T,x,x, x,x,x,x, x,x,T,T, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x},
+ {T,T,T,x, x,x,T,x, T,x,x,x, T,x,x,T, x,T,T,T, x,x,x,x, T,T,x,T, T,T,T,T, T,T,x,x, x,x,x,x, x,x,x,x, x,x,x,T, T,T,x,x, x,x,x,x, T,x,x,x, T,T,T,T, T,T,T,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,T,T, T,T,T,T, T,x,x,x, x,x,x,x, x,x,x},
+ {x,x,x,x, x,x,x,x, T,T,x,x, T,T,T,T, x,x,x,T, x,T,x,x, T,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,T,T, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x},
+ {x,x,x,x, x,x,x,x, T,x,x,x, T,T,T,T, x,x,x,T, x,T,x,x, T,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,T,T, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x},
+ {x,x,x,x, x,x,x,x, T,x,x,x, x,T,T,x, x,x,x,T, x,x,x,x, T,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,T,T, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x},
+ {T,x,x,x, x,x,T,T, T,T,x,x, T,T,T,T, x,x,x,T, x,T,T,x, T,T,x,x, x,x,T,T, T,T,x,x, x,x,x,x, x,x,T,T, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x},
{x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,T,T, T,x,x,x, x,x,x,x, x,x,x,x, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x},
{x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, T,T,T,T, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x},
- {x,T,x,T, x,x,x,x, x,x,x,x, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,T, T,T,T,T, T,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x},
+ {x,T,x,T, x,x,x,x, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,T, T,T,T,T, T,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x},
{T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, T,T,T,T, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x},
{x,T,T,x, x,x,T,x, x,x,x,x, x,x,x,x, x,T,x,T, x,x,x,x, x,x,x,x, x,x,x,x, x,T,x,x, x,x,T,T, x,x,x,x, x,x,x,x, x,x,x,x, T,x,x,x, T,x,x,x, x,x,T,T, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,T,x,x, x,x,T,x, x,T,T,T, T,T,T,T, T,x,x,T, T,T,T,x, x,x,x},
- {x,T,T,x, x,x,T,x, x,x,x,x, T,x,x,x, x,T,x,T, x,x,x,x, x,x,x,T, x,x,x,x, x,T,x,x, x,x,x,x, x,x,x,x, x,x,x,T, T,T,x,x, x,x,x,x, T,x,x,x, T,x,T,T, T,T,T,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,T,T, T,T,T,T, T,x,x,x, x,x,x,x, x,x,x},
+ {x,T,T,x, x,x,T,x, T,x,x,x, x,x,x,x, x,T,x,T, x,x,x,x, x,x,x,T, x,x,x,x, x,T,x,x, x,x,x,x, x,x,x,x, x,x,x,T, T,T,x,x, x,x,x,x, T,x,x,x, T,x,T,T, T,T,T,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,T,T, T,T,T,T, T,x,x,x, x,x,x,x, x,x,x},
{x,T,T,x, x,x,T,x, x,x,x,x, x,x,x,x, x,T,x,T, x,x,x,x, x,x,x,x, x,x,x,x, x,T,x,x, x,x,T,T, x,x,x,x, x,T,x,x, x,x,x,x, T,x,x,x, T,x,x,x, x,x,T,T, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,T,x,x, x,x,T,x, x,T,T,T, T,T,T,T, T,x,x,T, T,T,T,x, x,x,x},
- {T,T,T,x, x,x,T,x, x,x,x,x, T,x,x,x, x,T,x,T, x,x,x,x, x,x,x,T, x,x,x,x, x,T,x,x, x,x,x,x, x,x,x,x, x,x,x,T, T,T,x,x, x,x,x,x, T,x,x,x, T,x,T,T, T,T,T,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,T,T, T,T,T,T, T,x,x,x, x,x,x,x, x,x,x},
+ {T,T,T,x, x,x,T,x, T,x,x,x, x,x,x,x, x,T,x,T, x,x,x,x, x,x,x,T, x,x,x,x, x,T,x,x, x,x,x,x, x,x,x,x, x,x,x,T, T,T,x,x, x,x,x,x, T,x,x,x, T,x,T,T, T,T,T,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,T,T, T,T,T,T, T,x,x,x, x,x,x,x, x,x,x},
{x,x,x,x, x,x,T,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, T,T,x,x, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x},
{x,T,T,x, x,x,T,x, x,x,x,x, x,x,x,x, x,T,x,T, x,x,x,x, x,x,x,x, x,x,x,x, x,T,x,x, x,x,T,T, x,x,x,x, x,T,x,x, x,x,x,T, T,x,x,T, T,x,x,x, x,x,T,T, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,T,x,x, x,x,T,x, x,T,T,T, T,T,T,T, T,x,x,T, T,T,T,x, x,x,x},
{x,x,T,x, x,x,x,x, x,x,x,x, x,x,x,x, x,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,T,T, T,T,T,T, T,x,x,x, x,x,x,x, x,x,x},
@@ -2532,11 +2543,11 @@ public class Errors {
case 5: s = "colon expected"; break;
case 6: s = "lbrace expected"; break;
case 7: s = "rbrace expected"; break;
- case 8: s = "\"module\" expected"; break;
- case 9: s = "\"refines\" expected"; break;
- case 10: s = "\"imports\" expected"; break;
- case 11: s = "\"class\" expected"; break;
- case 12: s = "\"ghost\" expected"; break;
+ case 8: s = "\"ghost\" expected"; break;
+ case 9: s = "\"module\" expected"; break;
+ case 10: s = "\"refines\" expected"; break;
+ case 11: s = "\"imports\" expected"; break;
+ case 12: s = "\"class\" expected"; break;
case 13: s = "\"static\" expected"; break;
case 14: s = "\"unlimited\" expected"; break;
case 15: s = "\"datatype\" expected"; break;
@@ -2630,76 +2641,77 @@ public class Errors {
case 103: s = "\"::\" expected"; break;
case 104: s = "\"\\u2022\" expected"; break;
case 105: s = "??? expected"; break;
- case 106: s = "this symbol not expected in ClassDecl"; break;
- case 107: s = "this symbol not expected in DatatypeDecl"; break;
+ case 106: s = "invalid Dafny"; break;
+ case 107: s = "this symbol not expected in ClassDecl"; break;
case 108: s = "this symbol not expected in DatatypeDecl"; break;
- case 109: s = "this symbol not expected in ArbitraryTypeDecl"; break;
- case 110: s = "invalid ClassMemberDecl"; break;
- case 111: s = "this symbol not expected in FieldDecl"; break;
+ case 109: s = "this symbol not expected in DatatypeDecl"; break;
+ case 110: s = "this symbol not expected in ArbitraryTypeDecl"; break;
+ case 111: s = "invalid ClassMemberDecl"; break;
case 112: s = "this symbol not expected in FieldDecl"; break;
- case 113: s = "invalid FunctionDecl"; break;
+ case 113: s = "this symbol not expected in FieldDecl"; break;
case 114: s = "invalid FunctionDecl"; break;
case 115: s = "invalid FunctionDecl"; break;
- case 116: s = "this symbol not expected in MethodDecl"; break;
- case 117: s = "invalid MethodDecl"; break;
+ case 116: s = "invalid FunctionDecl"; break;
+ case 117: s = "this symbol not expected in MethodDecl"; break;
case 118: s = "invalid MethodDecl"; break;
- case 119: s = "invalid TypeAndToken"; break;
- case 120: s = "this symbol not expected in MethodSpec"; break;
+ case 119: s = "invalid MethodDecl"; break;
+ case 120: s = "invalid TypeAndToken"; break;
case 121: s = "this symbol not expected in MethodSpec"; break;
case 122: s = "this symbol not expected in MethodSpec"; break;
case 123: s = "this symbol not expected in MethodSpec"; break;
- case 124: s = "invalid MethodSpec"; break;
- case 125: s = "this symbol not expected in MethodSpec"; break;
- case 126: s = "invalid MethodSpec"; break;
- case 127: s = "invalid ReferenceType"; break;
- case 128: s = "this symbol not expected in FunctionSpec"; break;
+ case 124: s = "this symbol not expected in MethodSpec"; break;
+ case 125: s = "invalid MethodSpec"; break;
+ case 126: s = "this symbol not expected in MethodSpec"; break;
+ case 127: s = "invalid MethodSpec"; break;
+ case 128: s = "invalid ReferenceType"; break;
case 129: s = "this symbol not expected in FunctionSpec"; break;
case 130: s = "this symbol not expected in FunctionSpec"; break;
case 131: s = "this symbol not expected in FunctionSpec"; break;
case 132: s = "this symbol not expected in FunctionSpec"; break;
- case 133: s = "invalid FunctionSpec"; break;
- case 134: s = "invalid PossiblyWildFrameExpression"; break;
- case 135: s = "invalid PossiblyWildExpression"; break;
- case 136: s = "this symbol not expected in OneStmt"; break;
- case 137: s = "invalid OneStmt"; break;
- case 138: s = "this symbol not expected in OneStmt"; break;
- case 139: s = "invalid OneStmt"; break;
- case 140: s = "invalid AssertStmt"; break;
- case 141: s = "invalid UpdateStmt"; break;
- case 142: s = "invalid IfStmt"; break;
+ case 133: s = "this symbol not expected in FunctionSpec"; break;
+ case 134: s = "invalid FunctionSpec"; break;
+ case 135: s = "invalid PossiblyWildFrameExpression"; break;
+ case 136: s = "invalid PossiblyWildExpression"; break;
+ case 137: s = "this symbol not expected in OneStmt"; break;
+ case 138: s = "invalid OneStmt"; break;
+ case 139: s = "this symbol not expected in OneStmt"; break;
+ case 140: s = "invalid OneStmt"; break;
+ case 141: s = "invalid AssertStmt"; break;
+ case 142: s = "invalid UpdateStmt"; break;
case 143: s = "invalid IfStmt"; break;
- case 144: s = "invalid WhileStmt"; break;
+ case 144: s = "invalid IfStmt"; break;
case 145: s = "invalid WhileStmt"; break;
- case 146: s = "invalid Rhs"; break;
- case 147: s = "invalid Lhs"; break;
- case 148: s = "invalid Guard"; break;
- case 149: s = "this symbol not expected in LoopSpec"; break;
+ case 146: s = "invalid WhileStmt"; break;
+ case 147: s = "invalid Rhs"; break;
+ case 148: s = "invalid Lhs"; break;
+ case 149: s = "invalid Guard"; break;
case 150: s = "this symbol not expected in LoopSpec"; break;
case 151: s = "this symbol not expected in LoopSpec"; break;
case 152: s = "this symbol not expected in LoopSpec"; break;
case 153: s = "this symbol not expected in LoopSpec"; break;
- case 154: s = "this symbol not expected in Invariant"; break;
- case 155: s = "invalid AttributeArg"; break;
- case 156: s = "invalid EquivOp"; break;
- case 157: s = "invalid ImpliesOp"; break;
- case 158: s = "invalid AndOp"; break;
- case 159: s = "invalid OrOp"; break;
- case 160: s = "invalid RelOp"; break;
- case 161: s = "invalid AddOp"; break;
- case 162: s = "invalid UnaryExpression"; break;
- case 163: s = "invalid MulOp"; break;
- case 164: s = "invalid NegOp"; break;
- case 165: s = "invalid EndlessExpression"; break;
- case 166: s = "invalid Suffix"; break;
+ case 154: s = "this symbol not expected in LoopSpec"; break;
+ case 155: s = "this symbol not expected in Invariant"; break;
+ case 156: s = "invalid AttributeArg"; break;
+ case 157: s = "invalid EquivOp"; break;
+ case 158: s = "invalid ImpliesOp"; break;
+ case 159: s = "invalid AndOp"; break;
+ case 160: s = "invalid OrOp"; break;
+ case 161: s = "invalid RelOp"; break;
+ case 162: s = "invalid AddOp"; break;
+ case 163: s = "invalid UnaryExpression"; break;
+ case 164: s = "invalid MulOp"; break;
+ case 165: s = "invalid NegOp"; break;
+ case 166: s = "invalid EndlessExpression"; break;
case 167: s = "invalid Suffix"; break;
case 168: s = "invalid Suffix"; break;
- case 169: s = "invalid DisplayExpr"; break;
- case 170: s = "invalid MultiSetExpr"; break;
- case 171: s = "invalid ConstAtomExpression"; break;
- case 172: s = "invalid QuantifierGuts"; break;
- case 173: s = "invalid Forall"; break;
- case 174: s = "invalid Exists"; break;
- case 175: s = "invalid QSep"; break;
+ case 169: s = "invalid Suffix"; break;
+ case 170: s = "invalid DisplayExpr"; break;
+ case 171: s = "invalid MultiSetExpr"; break;
+ case 172: s = "invalid ConstAtomExpression"; break;
+ case 173: s = "invalid QuantifierGuts"; break;
+ case 174: s = "invalid Forall"; break;
+ case 175: s = "invalid Exists"; break;
+ case 176: s = "invalid QSep"; break;
default: s = "error " + n; break;
}
diff --git a/Source/Dafny/Printer.cs b/Source/Dafny/Printer.cs
index 351df668..28ce83f4 100644
--- a/Source/Dafny/Printer.cs
+++ b/Source/Dafny/Printer.cs
@@ -347,7 +347,7 @@ namespace Microsoft.Dafny {
void PrintDecreasesSpec(Specification<Expression> decs, int indent) {
Contract.Requires(decs != null);
- if (decs.Expressions.Count != 0) {
+ if (decs.Expressions != null && decs.Expressions.Count != 0) {
Indent(indent);
wr.Write("decreases");
if (decs.HasAttributes())
@@ -360,14 +360,14 @@ namespace Microsoft.Dafny {
}
}
- void PrintFrameSpecLine(string kind, List<FrameExpression/*!*/>/*!*/ ee, int indent, Attributes attrs) {
+ void PrintFrameSpecLine(string kind, List<FrameExpression/*!*/> ee, int indent, Attributes attrs) {
Contract.Requires(kind != null);
Contract.Requires(cce.NonNullElements(ee));
- if (ee.Count != 0) {
+ if (ee != null && ee.Count != 0) {
Indent(indent);
wr.Write("{0}", kind);
if (attrs != null) {
- PrintAttributes(attrs);
+ PrintAttributes(attrs);
}
wr.Write(" ");
PrintFrameExpressionList(ee);
diff --git a/Source/Dafny/RefinementTransformer.cs b/Source/Dafny/RefinementTransformer.cs
index 1626cdb4..36ae8f22 100644
--- a/Source/Dafny/RefinementTransformer.cs
+++ b/Source/Dafny/RefinementTransformer.cs
@@ -450,7 +450,7 @@ namespace Microsoft.Dafny {
} else if (stmt is IfStmt) {
var s = (IfStmt)stmt;
- r = new IfStmt(Tok(s.Tok), CloneExpr(s.Guard), CloneStmt(s.Thn), CloneStmt(s.Els));
+ r = new IfStmt(Tok(s.Tok), CloneExpr(s.Guard), CloneBlockStmt(s.Thn), CloneStmt(s.Els));
} else if (stmt is AlternativeStmt) {
var s = (AlternativeStmt)stmt;
@@ -458,7 +458,7 @@ namespace Microsoft.Dafny {
} else if (stmt is WhileStmt) {
var s = (WhileStmt)stmt;
- r = new WhileStmt(Tok(s.Tok), CloneExpr(s.Guard), s.Invariants.ConvertAll(CloneMayBeFreeExpr), CloneSpecExpr(s.Decreases), CloneSpecFrameExpr(s.Mod), CloneStmt(s.Body));
+ r = new WhileStmt(Tok(s.Tok), CloneExpr(s.Guard), s.Invariants.ConvertAll(CloneMayBeFreeExpr), CloneSpecExpr(s.Decreases), CloneSpecFrameExpr(s.Mod), CloneBlockStmt(s.Body));
} else if (stmt is AlternativeLoopStmt) {
var s = (AlternativeLoopStmt)stmt;
@@ -494,7 +494,11 @@ namespace Microsoft.Dafny {
void AddStmtLabels(Statement s, LabelNode node) {
if (node != null) {
AddStmtLabels(s, node.Next);
- s.Labels = new LabelNode(Tok(node.Tok), node.Label, s.Labels);
+ if (node.Label == null) {
+ // this indicates an implicit-target break statement that has been resolved; don't add it
+ } else {
+ s.Labels = new LabelNode(Tok(node.Tok), node.Label, s.Labels);
+ }
}
}
@@ -790,60 +794,258 @@ namespace Microsoft.Dafny {
* TODO: should also handle labels and some form of new "replace" statement
*/
if (cur is SkeletonStatement) {
- var ass = ((SkeletonStatement)cur).S as AssertStmt;
- if (ass != null) {
+ var S = ((SkeletonStatement)cur).S;
+ if (S == null) {
+ if (i + 1 == skeleton.Body.Count) {
+ // this "...;" is the last statement of the skeleton, so treat it like the default case
+ } else {
+ var nxt = skeleton.Body[i+1];
+ if (nxt is SkeletonStatement && ((SkeletonStatement)nxt).S == null) {
+ // "...; ...;" is the same as just "...;", so skip this one
+ } else {
+ // skip up until the next thing that matches "nxt"
+ while (!PotentialMatch(nxt, oldS)) {
+ // loop invariant: oldS == oldStmt.Body[j]
+ body.Add(CloneStmt(oldS));
+ j++;
+ if (j == oldStmt.Body.Count) { break; }
+ oldS = oldStmt.Body[j];
+ }
+ }
+ }
+ i++;
+
+ } else if (S is AssertStmt) {
+ var skel = (AssertStmt)S;
Contract.Assert(((SkeletonStatement)cur).ConditionOmitted);
var oldAssume = oldS as PredicateStmt;
if (oldAssume == null) {
- reporter.Error(cur.Tok, "assert template does not match old statement");
+ reporter.Error(cur.Tok, "assert template does not match inherited statement");
+ i++;
} else {
// Clone the expression, but among the new assert's attributes, indicate
// that this assertion is supposed to be translated into a check. That is,
// it is not allowed to be just assumed in the translation, despite the fact
// that the condition is inherited.
var e = CloneExpr(oldAssume.Expr);
- body.Add(new AssertStmt(ass.Tok, e, new Attributes("prependAssertToken", new List<Attributes.Argument>(), null)));
+ body.Add(new AssertStmt(skel.Tok, e, new Attributes("prependAssertToken", new List<Attributes.Argument>(), null)));
+ i++; j++;
+ }
+
+ } else if (S is IfStmt) {
+ var skel = (IfStmt)S;
+ Contract.Assert(((SkeletonStatement)cur).ConditionOmitted);
+ var oldIf = oldS as IfStmt;
+ if (oldIf == null) {
+ reporter.Error(cur.Tok, "if-statement template does not match inherited statement");
+ i++;
+ } else {
+ var resultingThen = MergeBlockStmt(skel.Thn, oldIf.Thn);
+ var resultingElse = MergeElse(skel.Els, oldIf.Els);
+ var r = new IfStmt(skel.Tok, skel.Guard, resultingThen, resultingElse);
+ body.Add(r);
+ i++; j++;
}
+
+ } else if (S is WhileStmt) {
+ var skel = (WhileStmt)S;
+ var oldWhile = oldS as WhileStmt;
+ if (oldWhile == null) {
+ reporter.Error(cur.Tok, "while-statement template does not match inherited statement");
+ i++;
+ } else {
+ Expression guard;
+ if (((SkeletonStatement)cur).ConditionOmitted) {
+ guard = CloneExpr(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");
+ }
+ guard = skel.Guard;
+ }
+ // Note, if the loop body is omitted in the skeleton, the parser will have set the loop body to an empty block,
+ // which has the same merging behavior.
+ var r = MergeWhileStmt(skel, oldWhile, guard);
+ body.Add(r);
+ i++; j++;
+ }
+
+ } else {
+ Contract.Assume(false); // unexpected skeleton statement
+ }
+
+ } else if (cur is AssertStmt) {
+ MergeAddStatement(cur, body);
+ i++;
+
+ } else if (cur is VarDeclStmt) {
+ var cNew = (VarDeclStmt)cur;
+ var cOld = oldS as VarDeclStmt;
+ if (cOld != null && cNew.Lhss.Count == 1 && cOld.Lhss.Count == 1 && cNew.Lhss[0].Name == cOld.Lhss[0].Name && cOld.Update == null) {
+ // Note, we allow switching between ghost and non-ghost, since that seems unproblematic.
+ // Go ahead with the merge:
+ body.Add(cNew);
i++; j++;
} else {
- reporter.Error(cur.Tok, "sorry, this skeleton statement is not yet supported");
+ MergeAddStatement(cur, body);
i++;
}
- } else {
- var cNew = cur as VarDeclStmt;
- var cOld = oldS as VarDeclStmt;
- if (cNew != null && cOld != null && cNew.Lhss.Count == 1 && cOld.Lhss.Count == 1 &&
- cNew.Lhss[0].Name == cOld.Lhss[0].Name && cOld.Update == null) {
- body.Add(cNew); // TODO: there should perhaps be some more validity checks here first
+
+ } else if (cur is IfStmt) {
+ var cNew = (IfStmt)cur;
+ var cOld = oldS as IfStmt;
+ if (cOld != null && cOld.Guard == null) {
+ var r = new IfStmt(cNew.Tok, cNew.Guard, MergeBlockStmt(cNew.Thn, cOld.Thn), MergeElse(cNew.Els, cOld.Els));
+ body.Add(r);
i++; j++;
} else {
MergeAddStatement(cur, body);
i++;
}
+
+ } else if (cur is WhileStmt) {
+ var cNew = (WhileStmt)cur;
+ var cOld = oldS as WhileStmt;
+ if (cOld != null && cOld.Guard == null) {
+ var r = MergeWhileStmt(cNew, cOld, cNew.Guard);
+ body.Add(r);
+ i++; j++;
+ } else {
+ MergeAddStatement(cur, body);
+ i++;
+ }
+
+ } else {
+ MergeAddStatement(cur, body);
+ i++;
}
}
}
// implement the implicit "...;" at the end of each block statement skeleton
for (; j < oldStmt.Body.Count; j++) {
- MergeAddStatement(CloneStmt(oldStmt.Body[j]), body);
+ body.Add(CloneStmt(oldStmt.Body[j]));
}
return new BlockStmt(skeleton.Tok, body);
}
+ bool PotentialMatch(Statement nxt, Statement other) {
+ Contract.Requires(!(nxt is SkeletonStatement) || ((SkeletonStatement)nxt).S != null); // nxt is not "...;"
+ Contract.Requires(other != null);
+
+ if (nxt is SkeletonStatement) {
+ var S = ((SkeletonStatement)nxt).S;
+ if (S is AssertStmt) {
+ return other is PredicateStmt;
+ } else if (S is IfStmt) {
+ return other is IfStmt;
+ } else if (S is WhileStmt) {
+ return other is WhileStmt;
+ } else {
+ Contract.Assume(false); // unexpected skeleton
+ }
+
+ } else if (nxt is IfStmt) {
+ var oth = other as IfStmt;
+ return oth != null && oth.Guard == null;
+ } else if (nxt is WhileStmt) {
+ var oth = other as WhileStmt;
+ return oth != null && oth.Guard == null;
+ }
+
+ // not a potential match
+ return false;
+ }
+
+ WhileStmt MergeWhileStmt(WhileStmt cNew, WhileStmt cOld, Expression guard) {
+ Contract.Requires(cNew != null);
+ Contract.Requires(cOld != null);
+
+ // Note, the parser produces errors if there are any decreases or modifies clauses (and it creates
+ // the Specification structures with a null list).
+ Contract.Assume(cNew.Decreases.Expressions == null);
+ Contract.Assume(cNew.Mod.Expressions == null);
+
+ var invs = cOld.Invariants.ConvertAll(CloneMayBeFreeExpr);
+ invs.AddRange(cNew.Invariants);
+ var r = new WhileStmt(cNew.Tok, guard, invs, CloneSpecExpr(cOld.Decreases), CloneSpecFrameExpr(cOld.Mod), MergeBlockStmt(cNew.Body, cOld.Body));
+ return r;
+ }
+
+ Statement MergeElse(Statement skeleton, Statement oldStmt) {
+ Contract.Requires(skeleton == null || skeleton is BlockStmt || skeleton is IfStmt);
+ Contract.Requires(oldStmt == null || oldStmt is BlockStmt || oldStmt is IfStmt);
+
+ if (skeleton == null) {
+ return CloneStmt(oldStmt);
+ } else if (skeleton is IfStmt) {
+ // wrap a block statement around the if statement
+ skeleton = new BlockStmt(skeleton.Tok, new List<Statement>() { skeleton });
+ }
+
+ if (oldStmt == null) {
+ // make it into an empty block statement
+ oldStmt = new BlockStmt(skeleton.Tok, new List<Statement>());
+ } else if (oldStmt is IfStmt) {
+ // wrap a block statement around the if statement
+ oldStmt = new BlockStmt(oldStmt.Tok, new List<Statement>() { oldStmt });
+ }
+
+ Contract.Assert(skeleton is BlockStmt && oldStmt is BlockStmt);
+ return MergeBlockStmt((BlockStmt)skeleton, (BlockStmt)oldStmt);
+ }
+
/// <summary>
- /// Add "s" to "stmtList", but complain if "s" contains further occurrences of "..." or if "s" assigns to a
- /// variable that was not declared in the refining module.
- /// TODO: and what about new control flow?
+ /// Add "s" to "stmtList", but complain if "s" contains further occurrences of "...", if "s" assigns to a
+ /// variable that was not declared in the refining module, or if "s" has some control flow that jumps to a
+ /// place outside "s".
/// </summary>
void MergeAddStatement(Statement s, List<Statement> stmtList) {
Contract.Requires(s != null);
Contract.Requires(stmtList != null);
- if (s is AssertStmt) {
- // this is fine to add
+ var prevErrorCount = reporter.ErrorCount;
+ CheckIsOkayNewStatement(s, new Stack<string>(), 0);
+ if (reporter.ErrorCount == prevErrorCount) {
+ stmtList.Add(s);
+ }
+ }
+
+ /// <summary>
+ /// See comment on MergeAddStatement.
+ /// </summary>
+ void CheckIsOkayNewStatement(Statement s, Stack<string> labels, int loopLevels) {
+ Contract.Requires(s != null);
+ Contract.Requires(labels != null);
+ Contract.Requires(0 <= loopLevels);
+
+ for (LabelNode n = s.Labels; n != null; n = n.Next) {
+ labels.Push(n.Label);
+ }
+
+ 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");
+ } else if (s is ReturnStmt) {
+ reporter.Error(s, "return 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");
+ }
+ } 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.
} else {
- // TODO: validity checks
+ if (s is WhileStmt || s is AlternativeLoopStmt) {
+ loopLevels++;
+ }
+ foreach (var ss in s.SubStatements) {
+ CheckIsOkayNewStatement(ss, labels, loopLevels);
+ }
+ }
+
+ for (LabelNode n = s.Labels; n != null; n = n.Next) {
+ labels.Pop();
}
- stmtList.Add(s);
}
// ---------------------- additional methods -----------------------------------------------------------------------------
diff --git a/Source/Dafny/Resolver.cs b/Source/Dafny/Resolver.cs
index f66a2c5c..b259e426 100644
--- a/Source/Dafny/Resolver.cs
+++ b/Source/Dafny/Resolver.cs
@@ -170,19 +170,21 @@ namespace Microsoft.Dafny {
}
// register top-level declarations
+ Rewriter rewriter = new AutoContractsRewriter();
var systemNameInfo = RegisterTopLevelDecls(prog.BuiltIns.SystemModule.TopLevelDecls);
var moduleNameInfo = new ModuleNameInformation[h];
+ var datatypeDependencies = new Graph<DatatypeDecl>();
foreach (var m in mm) {
+ rewriter.PreResolve(m);
if (m.RefinementBase != null) {
var transformer = new RefinementTransformer(this);
transformer.Construct(m);
}
moduleNameInfo[m.Height] = RegisterTopLevelDecls(m.TopLevelDecls);
- }
+// }
// resolve top-level declarations
- Graph<DatatypeDecl> datatypeDependencies = new Graph<DatatypeDecl>();
- foreach (ModuleDecl m in mm) {
+// foreach (ModuleDecl m in mm) {
// set up environment
ModuleNameInformation info = ModuleNameInformation.Merge(m, systemNameInfo, moduleNameInfo);
classes = info.Classes;
@@ -193,6 +195,8 @@ namespace Microsoft.Dafny {
// tear down
classes = null;
allDatatypeCtors = null;
+ // give rewriter a chance to do processing
+ rewriter.PostResolve(m);
}
// compute IsRecursive bit for mutually recursive functions
@@ -1733,8 +1737,7 @@ namespace Microsoft.Dafny {
if (arrayRangeLhs == null && !sse.SelectOne) {
arrayRangeLhs = sse;
}
- }
- else {
+ } else {
ResolveExpression(lhs, true);
}
}
diff --git a/Source/Dafny/Rewriter.cs b/Source/Dafny/Rewriter.cs
new file mode 100644
index 00000000..addcce0a
--- /dev/null
+++ b/Source/Dafny/Rewriter.cs
@@ -0,0 +1,321 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics.Contracts;
+
+namespace Microsoft.Dafny
+{
+ public interface Rewriter
+ {
+ void PreResolve(ModuleDecl m);
+ void PostResolve(ModuleDecl m);
+ }
+
+ /// <summary>
+ /// AutoContracts is an experimental feature that will fill much of the dynamic-frames boilerplate
+ /// into a class. From the user's perspective, what needs to be done is simply:
+ /// - mark the class with {:autocontracts}
+ /// - declare a function (or predicate) called Valid()
+ ///
+ /// AutoContracts will then:
+ ///
+ /// Declare:
+ /// ghost var Repr: set(object);
+ ///
+ /// For function/predicate Valid(), insert:
+ /// reads this, Repr;
+ /// Into body of Valid(), insert (at the beginning of the body):
+ /// this in Repr && null !in Repr
+ /// and also insert, for every array-valued field A declared in the class:
+ /// (A != null ==> A in Repr) &&
+ /// and for every field F of a class type T where T has a field called Repr, also insert:
+ /// (F != null ==> F in Repr && F.Repr SUBSET Repr && this !in Repr)
+ /// Except, if A or F is declared with {:autocontracts false}, then the implication will not
+ /// be added.
+ ///
+ /// For every constructor, add:
+ /// modifies this;
+ /// ensures Valid() && fresh(Repr - {this});
+ /// At the end of the body of the constructor, add:
+ /// Repr := {this};
+ /// if (A != null) { Repr := Repr + {A}; }
+ /// if (F != null) { Repr := Repr + {F} + F.Repr; }
+ ///
+ /// For every method, add:
+ /// requires Valid();
+ /// modifies Repr;
+ /// ensures Valid() && fresh(Repr - old(Repr));
+ /// At the end of the body of the method, add:
+ /// if (A != null) { Repr := Repr + {A}; }
+ /// if (F != null) { Repr := Repr + {F} + F.Repr; }
+ /// </summary>
+ public class AutoContractsRewriter : Rewriter
+ {
+ public void PreResolve(ModuleDecl m) {
+ foreach (var d in m.TopLevelDecls) {
+ bool sayYes = true;
+ if (d is ClassDecl && Attributes.ContainsBool(d.Attributes, "autocontracts", ref sayYes) && sayYes) {
+ ProcessClassPreResolve((ClassDecl)d);
+ }
+ }
+ }
+
+ void ProcessClassPreResolve(ClassDecl cl) {
+ // Add: ghost var Repr: set<object>;
+ // ...unless a field with that name is already present
+ if (!cl.Members.Exists(member => member is Field && member.Name == "Repr")) {
+ Type ty = new SetType(new ObjectType());
+ cl.Members.Add(new Field(cl.tok, "Repr", true, ty, null));
+ }
+
+ foreach (var member in cl.Members) {
+ bool sayYes = true;
+ if (Attributes.ContainsBool(member.Attributes, "autocontracts", ref sayYes) && !sayYes) {
+ continue;
+ }
+ var tok = member.tok;
+ if (member is Function && member.Name == "Valid" && !member.IsStatic) {
+ var valid = (Function)member;
+ // reads this;
+ valid.Reads.Add(new FrameExpression(new ThisExpr(tok), null));
+ // reads Repr;
+ valid.Reads.Add(new FrameExpression(new FieldSelectExpr(tok, new ImplicitThisExpr(tok), "Repr"), null));
+ } else if (member is Constructor) {
+ var ctor = (Constructor)member;
+ // modifies this;
+ ctor.Mod.Expressions.Add(new FrameExpression(new ImplicitThisExpr(tok), null));
+ // ensures Valid();
+ ctor.Ens.Insert(0, new MaybeFreeExpression(new FunctionCallExpr(tok, "Valid", new ImplicitThisExpr(tok), tok, new List<Expression>())));
+ // ensures fresh(Repr - {this});
+ var freshness = new FreshExpr(tok, new BinaryExpr(tok, BinaryExpr.Opcode.Sub,
+ new FieldSelectExpr(tok, new ImplicitThisExpr(tok), "Repr"),
+ new SetDisplayExpr(tok, new List<Expression>() { new ThisExpr(tok) })));
+ ctor.Ens.Insert(1, new MaybeFreeExpression(freshness));
+ } else if (member is Method && !member.IsStatic) {
+ var m = (Method)member;
+ // requires Valid();
+ m.Req.Insert(0, new MaybeFreeExpression(new FunctionCallExpr(tok, "Valid", new ImplicitThisExpr(tok), tok, new List<Expression>())));
+ // If this is a mutating method, we should also add a modifies clause and a postcondition, but we don't do that if it's
+ // a simple query method. However, we won't know if it's a simple query method until after resolution, so we'll add the
+ // rest of the spec then.
+ }
+ }
+ }
+
+ public void PostResolve(ModuleDecl m) {
+ foreach (var d in m.TopLevelDecls) {
+ bool sayYes = true;
+ if (d is ClassDecl && Attributes.ContainsBool(d.Attributes, "autocontracts", ref sayYes) && sayYes) {
+ ProcessClassPostResolve((ClassDecl)d);
+ }
+ }
+ }
+
+ 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"
+ Field ReprField = null;
+ Function Valid = null;
+ var subobjects = new List<Tuple<Field, Field>>();
+ foreach (var member in cl.Members) {
+ var field = member as Field;
+ if (field != null) {
+ bool sayYes = true;
+ if (field.Name == "Repr") {
+ ReprField = field;
+ } else if (Attributes.ContainsBool(field.Attributes, "autocontracts", ref sayYes) && !sayYes) {
+ // ignore this field
+ } else if (field.Type is ObjectType) {
+ subobjects.Add(new Tuple<Field, Field>(field, null));
+ } else if (field.Type.IsRefType) {
+ var rcl = (ClassDecl)((UserDefinedType)field.Type).ResolvedClass;
+ Field rRepr = null;
+ foreach (var memb in rcl.Members) {
+ var f = memb as Field;
+ if (f != null && f.Name == "Repr") {
+ rRepr = f;
+ break;
+ }
+ }
+ subobjects.Add(new Tuple<Field, Field>(field, rRepr));
+ }
+ } else if (member is Function && member.Name == "Valid" && !member.IsStatic) {
+ var fn = (Function)member;
+ if (fn.Formals.Count == 0 && fn.ResultType is BoolType) {
+ Valid = fn;
+ }
+ }
+ }
+ Contract.Assert(ReprField != null); // we expect there to be a "Repr" field, since we added one in PreResolve
+
+ Type ty = new UserDefinedType(cl.tok, cl.Name, cl, new List<Type>());
+ var self = new ThisExpr(cl.tok);
+ self.Type = ty;
+ var implicitSelf = new ImplicitThisExpr(cl.tok);
+ implicitSelf.Type = ty;
+ var Repr = new FieldSelectExpr(cl.tok, implicitSelf, "Repr");
+ Repr.Field = ReprField;
+ Repr.Type = ReprField.Type;
+ var cNull = new LiteralExpr(cl.tok);
+ cNull.Type = new ObjectType();
+
+ foreach (var member in cl.Members) {
+ bool sayYes = true;
+ if (Attributes.ContainsBool(member.Attributes, "autocontracts", ref sayYes) && !sayYes) {
+ continue;
+ }
+ var tok = member.tok;
+ if (member is Function && member.Name == "Valid" && !member.IsStatic) {
+ var valid = (Function)member;
+ if (valid.IsGhost && valid.ResultType is BoolType) {
+ var c0 = BinBoolExpr(tok, BinaryExpr.ResolvedOpcode.InSet, self, Repr); // this in Repr
+ var c1 = BinBoolExpr(tok, BinaryExpr.ResolvedOpcode.NotInSet, cNull, Repr); // null !in Repr
+ var c = BinBoolExpr(tok, BinaryExpr.ResolvedOpcode.And, c0, c1);
+
+ foreach (var ff in subobjects) {
+ var F = new FieldSelectExpr(tok, implicitSelf, ff.Item1.Name);
+ F.Field = ff.Item1;
+ F.Type = ff.Item1.Type;
+
+ c0 = BinBoolExpr(tok, BinaryExpr.ResolvedOpcode.NeqCommon, F, cNull);
+ c1 = BinBoolExpr(tok, BinaryExpr.ResolvedOpcode.InSet, F, Repr);
+ if (ff.Item2 == null) {
+ // F != null ==> F in Repr (so, nothing else to do)
+ } else {
+ // F != null ==> F in Repr && F.Repr <= Repr && this !in F.Repr
+ var FRepr = new FieldSelectExpr(tok, F, ff.Item2.Name);
+ FRepr.Field = ff.Item2;
+ FRepr.Type = ff.Item2.Type;
+ var c2 = BinBoolExpr(tok, BinaryExpr.ResolvedOpcode.Subset, FRepr, Repr);
+ var c3 = BinBoolExpr(tok, BinaryExpr.ResolvedOpcode.NotInSet, self, FRepr);
+ c1 = BinBoolExpr(tok, BinaryExpr.ResolvedOpcode.And, c1, BinBoolExpr(tok, BinaryExpr.ResolvedOpcode.And, c2, c3));
+ }
+ c = BinBoolExpr(tok, BinaryExpr.ResolvedOpcode.And, c, BinBoolExpr(tok, BinaryExpr.ResolvedOpcode.Imp, c0, c1));
+ }
+
+ if (valid.Body == null) {
+ valid.Body = c;
+ } else {
+ valid.Body = BinBoolExpr(tok, BinaryExpr.ResolvedOpcode.And, c, valid.Body);
+ }
+ }
+
+ } else if (member is Constructor) {
+ var ctor = (Constructor)member;
+ if (ctor.Body == null) {
+ ctor.Body = new BlockStmt(tok, new List<Statement>());
+ }
+ // TODO: these assignments should be included on every return path
+ var bodyStatements = ((BlockStmt)ctor.Body).Body;
+ // Repr := {this};
+ var e = new SetDisplayExpr(tok, new List<Expression>() { self });
+ e.Type = new SetType(new ObjectType());
+ Statement s = new AssignStmt(tok, Repr, new ExprRhs(e));
+ s.IsGhost = true;
+ bodyStatements.Add(s);
+
+ AddSubobjectReprs(tok, subobjects, bodyStatements, self, implicitSelf, cNull, Repr);
+
+ } else if (member is Method && !member.IsStatic) {
+ var m = (Method)member;
+ if (Valid != null && !IsSimpleQueryMethod(m)) {
+ // modifies Repr;
+ m.Mod.Expressions.Add(new FrameExpression(Repr, null));
+ // ensures Valid();
+ var valid = new FunctionCallExpr(tok, "Valid", implicitSelf, tok, new List<Expression>());
+ valid.Function = Valid;
+ valid.Type = Type.Bool;
+ m.Ens.Insert(0, new MaybeFreeExpression(valid));
+ // ensures fresh(Repr - old(Repr));
+ var e0 = new OldExpr(tok, Repr);
+ e0.Type = Repr.Type;
+ var e1 = new BinaryExpr(tok, BinaryExpr.Opcode.Sub, Repr, e0);
+ e1.ResolvedOp = BinaryExpr.ResolvedOpcode.SetDifference;
+ e1.Type = Repr.Type;
+ var freshness = new FreshExpr(tok, e1);
+ freshness.Type = Type.Bool;
+ m.Ens.Insert(1, new MaybeFreeExpression(freshness));
+
+ if (m.Body == null) {
+ m.Body = new BlockStmt(tok, new List<Statement>());
+ }
+ // TODO: these assignments should be included on every return path
+ var bodyStatements = ((BlockStmt)m.Body).Body;
+ AddSubobjectReprs(tok, subobjects, bodyStatements, self, implicitSelf, cNull, Repr);
+ }
+ }
+ }
+ }
+
+ void AddSubobjectReprs(Boogie.IToken tok, List<Tuple<Field, Field>> subobjects, List<Statement> bodyStatements,
+ Expression self, Expression implicitSelf, Expression cNull, Expression Repr) {
+
+ foreach (var ff in subobjects) {
+ var F = new FieldSelectExpr(tok, implicitSelf, ff.Item1.Name);
+ F.Field = ff.Item1;
+ F.Type = ff.Item1.Type;
+
+ Expression e = new SetDisplayExpr(tok, new List<Expression>() { F });
+ e.Type = new SetType(new ObjectType());
+ var rhs = new BinaryExpr(tok, BinaryExpr.Opcode.Add, Repr, e);
+ rhs.ResolvedOp = BinaryExpr.ResolvedOpcode.Union;
+ rhs.Type = Repr.Type;
+ if (ff.Item2 == null) {
+ // Repr := Repr + {F} (so, nothing else to do)
+ } else {
+ // Repr := Repr + {F} + F.Repr
+ var FRepr = new FieldSelectExpr(tok, F, ff.Item2.Name);
+ FRepr.Field = ff.Item2;
+ FRepr.Type = ff.Item2.Type;
+ rhs = new BinaryExpr(tok, BinaryExpr.Opcode.Add, rhs, FRepr);
+ rhs.ResolvedOp = BinaryExpr.ResolvedOpcode.Union;
+ rhs.Type = Repr.Type;
+ }
+ // Repr := Repr + ...;
+ Statement s = new AssignStmt(tok, Repr, new ExprRhs(rhs));
+ s.IsGhost = true;
+ // wrap if statement around s
+ e = BinBoolExpr(tok, BinaryExpr.ResolvedOpcode.NeqCommon, F, cNull);
+ var thn = new BlockStmt(tok, new List<Statement>() { s });
+ thn.IsGhost = true;
+ s = new IfStmt(tok, e, thn, null);
+ s.IsGhost = true;
+ // finally, add s to the body
+ bodyStatements.Add(s);
+ }
+ }
+
+ bool IsSimpleQueryMethod(Method m) {
+ // A simple query method has out parameters, its body has no effect other than to assign to them,
+ // and the postcondition does not explicitly mention the pre-state.
+ return m.Outs.Count != 0 && m.Body != null && LocalAssignsOnly(m.Body) &&
+ m.Ens.TrueForAll(mfe => !Translator.MentionsOldState(mfe.E));
+ }
+
+ bool LocalAssignsOnly(Statement s) {
+ Contract.Requires(s != null);
+ if (s is AssignStmt) {
+ var ss = (AssignStmt)s;
+ return ss.Lhs.Resolved is IdentifierExpr;
+ } else if (s is UpdateStmt) {
+ var ss = (UpdateStmt)s;
+ return ss.Lhss.TrueForAll(e => e.Resolved is IdentifierExpr);
+ } else if (s is CallStmt) {
+ return false;
+ } else {
+ foreach (var ss in s.SubStatements) {
+ if (!LocalAssignsOnly(ss)) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ BinaryExpr BinBoolExpr(Boogie.IToken tok, BinaryExpr.ResolvedOpcode rop, Expression e0, Expression e1) {
+ var p = new BinaryExpr(tok, BinaryExpr.ResolvedOp2SyntacticOp(rop), e0, e1);
+ p.ResolvedOp = rop;
+ p.Type = Type.Bool;
+ return p;
+ }
+ }
+}
diff --git a/Source/Dafny/Scanner.cs b/Source/Dafny/Scanner.cs
index 56d53e19..3e021fa5 100644
--- a/Source/Dafny/Scanner.cs
+++ b/Source/Dafny/Scanner.cs
@@ -488,11 +488,11 @@ public class Scanner {
void CheckLiteral() {
switch (t.val) {
- case "module": t.kind = 8; break;
- case "refines": t.kind = 9; break;
- case "imports": t.kind = 10; break;
- case "class": t.kind = 11; break;
- case "ghost": t.kind = 12; break;
+ case "ghost": t.kind = 8; break;
+ case "module": t.kind = 9; break;
+ case "refines": t.kind = 10; break;
+ case "imports": t.kind = 11; break;
+ case "class": t.kind = 12; break;
case "static": t.kind = 13; break;
case "unlimited": t.kind = 14; break;
case "datatype": t.kind = 15; break;
diff --git a/Source/Dafny/Translator.cs b/Source/Dafny/Translator.cs
index c0a56d05..6ca1ad01 100644
--- a/Source/Dafny/Translator.cs
+++ b/Source/Dafny/Translator.cs
@@ -2406,10 +2406,21 @@ namespace Microsoft.Dafny {
} else if (expr is LetExpr) {
var e = (LetExpr)expr;
- foreach (var rhs in e.RHSs) {
- CheckWellformed(rhs, options, locals, builder, etran);
+
+ var substMap = new Dictionary<IVariable, Expression>();
+ Contract.Assert(e.Vars.Count == e.RHSs.Count); // checked by resolution
+ for (int i = 0; i < e.Vars.Count; i++) {
+ var vr = e.Vars[i];
+ var tp = TrType(vr.Type);
+ var v = new Bpl.LocalVariable(vr.tok, new Bpl.TypedIdent(vr.tok, vr.UniqueName, tp));
+ locals.Add(v);
+ var lhs = new Bpl.IdentifierExpr(vr.tok, vr.UniqueName, tp);
+
+ CheckWellformedWithResult(e.RHSs[i], options, lhs, vr.Type, locals, builder, etran);
+ substMap.Add(vr, new BoogieWrapper(lhs, vr.Type));
}
- CheckWellformedWithResult(etran.GetSubstitutedBody(e), options, result, resultType, locals, builder, etran);
+ CheckWellformedWithResult(Substitute(e.Body, null, substMap), options, result, resultType, locals, builder, etran);
+ result = null;
} else if (expr is ComprehensionExpr) {
var e = (ComprehensionExpr)expr;
@@ -7061,7 +7072,7 @@ namespace Microsoft.Dafny {
/// <summary>
/// Returns true iff 'expr' is a two-state expression, that is, if it mentions "old(...)" or "fresh(...)".
/// </summary>
- static bool MentionsOldState(Expression expr) {
+ public static bool MentionsOldState(Expression expr) {
Contract.Requires(expr != null);
if (expr is OldExpr || expr is FreshExpr) {
return true;
diff --git a/Source/GPUVerify.sln b/Source/GPUVerify.sln
index a78d449e..a31d8600 100644
--- a/Source/GPUVerify.sln
+++ b/Source/GPUVerify.sln
@@ -21,22 +21,16 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AbsInt", "AbsInt\AbsInt.csp
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Houdini", "Houdini\Houdini.csproj", "{CF41E903-78EB-43BA-A355-E5FEB5ECECD4}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Isabelle", "Provers\Isabelle\Isabelle.csproj", "{435D5BD0-6F62-49F8-BB24-33E2257519AD}"
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Z3", "Provers\Z3\Z3.csproj", "{BB49B90B-BE21-4BE8-85BA-359FDB55F4DF}"
-EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SMTLib", "Provers\SMTLib\SMTLib.csproj", "{9B163AA3-36BC-4AFB-88AB-79BC9E97E401}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TPTP", "Provers\TPTP\TPTP.csproj", "{A598ED5A-93AD-4125-A555-3921A2F936FA}"
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Simplify", "Provers\Simplify\Simplify.csproj", "{FEE9F01B-9722-4A76-A24B-72A4016DFA8E}"
-EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VCGeneration", "VCGeneration\VCGeneration.csproj", "{E1F10180-C7B9-4147-B51F-FA1B701966DC}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Model", "Model\Model.csproj", "{ACEF88D5-DADD-46DA-BAE1-2144D63F4C83}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VCExpr", "VCExpr\VCExpr.csproj", "{56FFDBCA-7D14-43B8-A6CA-22A20E417EE1}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Isabelle", "Provers\Isabelle\Isabelle.csproj", "{435D5BD0-6F62-49F8-BB24-33E2257519AD}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Checked|Any CPU = Checked|Any CPU
@@ -255,46 +249,6 @@ Global
{CF41E903-78EB-43BA-A355-E5FEB5ECECD4}.z3apidebug|Mixed Platforms.ActiveCfg = Checked|Any CPU
{CF41E903-78EB-43BA-A355-E5FEB5ECECD4}.z3apidebug|Mixed Platforms.Build.0 = Checked|Any CPU
{CF41E903-78EB-43BA-A355-E5FEB5ECECD4}.z3apidebug|x86.ActiveCfg = Checked|Any CPU
- {435D5BD0-6F62-49F8-BB24-33E2257519AD}.Checked|Any CPU.ActiveCfg = Checked|Any CPU
- {435D5BD0-6F62-49F8-BB24-33E2257519AD}.Checked|Any CPU.Build.0 = Checked|Any CPU
- {435D5BD0-6F62-49F8-BB24-33E2257519AD}.Checked|Mixed Platforms.ActiveCfg = Checked|Any CPU
- {435D5BD0-6F62-49F8-BB24-33E2257519AD}.Checked|Mixed Platforms.Build.0 = Checked|Any CPU
- {435D5BD0-6F62-49F8-BB24-33E2257519AD}.Checked|x86.ActiveCfg = Checked|Any CPU
- {435D5BD0-6F62-49F8-BB24-33E2257519AD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {435D5BD0-6F62-49F8-BB24-33E2257519AD}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {435D5BD0-6F62-49F8-BB24-33E2257519AD}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
- {435D5BD0-6F62-49F8-BB24-33E2257519AD}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
- {435D5BD0-6F62-49F8-BB24-33E2257519AD}.Debug|x86.ActiveCfg = Debug|Any CPU
- {435D5BD0-6F62-49F8-BB24-33E2257519AD}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {435D5BD0-6F62-49F8-BB24-33E2257519AD}.Release|Any CPU.Build.0 = Release|Any CPU
- {435D5BD0-6F62-49F8-BB24-33E2257519AD}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
- {435D5BD0-6F62-49F8-BB24-33E2257519AD}.Release|Mixed Platforms.Build.0 = Release|Any CPU
- {435D5BD0-6F62-49F8-BB24-33E2257519AD}.Release|x86.ActiveCfg = Release|Any CPU
- {435D5BD0-6F62-49F8-BB24-33E2257519AD}.z3apidebug|Any CPU.ActiveCfg = z3apidebug|Any CPU
- {435D5BD0-6F62-49F8-BB24-33E2257519AD}.z3apidebug|Any CPU.Build.0 = z3apidebug|Any CPU
- {435D5BD0-6F62-49F8-BB24-33E2257519AD}.z3apidebug|Mixed Platforms.ActiveCfg = z3apidebug|Any CPU
- {435D5BD0-6F62-49F8-BB24-33E2257519AD}.z3apidebug|Mixed Platforms.Build.0 = z3apidebug|Any CPU
- {435D5BD0-6F62-49F8-BB24-33E2257519AD}.z3apidebug|x86.ActiveCfg = z3apidebug|Any CPU
- {BB49B90B-BE21-4BE8-85BA-359FDB55F4DF}.Checked|Any CPU.ActiveCfg = Checked|Any CPU
- {BB49B90B-BE21-4BE8-85BA-359FDB55F4DF}.Checked|Any CPU.Build.0 = Checked|Any CPU
- {BB49B90B-BE21-4BE8-85BA-359FDB55F4DF}.Checked|Mixed Platforms.ActiveCfg = Checked|Any CPU
- {BB49B90B-BE21-4BE8-85BA-359FDB55F4DF}.Checked|Mixed Platforms.Build.0 = Checked|Any CPU
- {BB49B90B-BE21-4BE8-85BA-359FDB55F4DF}.Checked|x86.ActiveCfg = Checked|Any CPU
- {BB49B90B-BE21-4BE8-85BA-359FDB55F4DF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {BB49B90B-BE21-4BE8-85BA-359FDB55F4DF}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {BB49B90B-BE21-4BE8-85BA-359FDB55F4DF}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
- {BB49B90B-BE21-4BE8-85BA-359FDB55F4DF}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
- {BB49B90B-BE21-4BE8-85BA-359FDB55F4DF}.Debug|x86.ActiveCfg = Debug|Any CPU
- {BB49B90B-BE21-4BE8-85BA-359FDB55F4DF}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {BB49B90B-BE21-4BE8-85BA-359FDB55F4DF}.Release|Any CPU.Build.0 = Release|Any CPU
- {BB49B90B-BE21-4BE8-85BA-359FDB55F4DF}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
- {BB49B90B-BE21-4BE8-85BA-359FDB55F4DF}.Release|Mixed Platforms.Build.0 = Release|Any CPU
- {BB49B90B-BE21-4BE8-85BA-359FDB55F4DF}.Release|x86.ActiveCfg = Release|Any CPU
- {BB49B90B-BE21-4BE8-85BA-359FDB55F4DF}.z3apidebug|Any CPU.ActiveCfg = z3apidebug|Any CPU
- {BB49B90B-BE21-4BE8-85BA-359FDB55F4DF}.z3apidebug|Any CPU.Build.0 = z3apidebug|Any CPU
- {BB49B90B-BE21-4BE8-85BA-359FDB55F4DF}.z3apidebug|Mixed Platforms.ActiveCfg = z3apidebug|Any CPU
- {BB49B90B-BE21-4BE8-85BA-359FDB55F4DF}.z3apidebug|Mixed Platforms.Build.0 = z3apidebug|Any CPU
- {BB49B90B-BE21-4BE8-85BA-359FDB55F4DF}.z3apidebug|x86.ActiveCfg = z3apidebug|Any CPU
{9B163AA3-36BC-4AFB-88AB-79BC9E97E401}.Checked|Any CPU.ActiveCfg = Checked|Any CPU
{9B163AA3-36BC-4AFB-88AB-79BC9E97E401}.Checked|Any CPU.Build.0 = Checked|Any CPU
{9B163AA3-36BC-4AFB-88AB-79BC9E97E401}.Checked|Mixed Platforms.ActiveCfg = Checked|Any CPU
@@ -315,46 +269,6 @@ Global
{9B163AA3-36BC-4AFB-88AB-79BC9E97E401}.z3apidebug|Mixed Platforms.ActiveCfg = z3apidebug|Any CPU
{9B163AA3-36BC-4AFB-88AB-79BC9E97E401}.z3apidebug|Mixed Platforms.Build.0 = z3apidebug|Any CPU
{9B163AA3-36BC-4AFB-88AB-79BC9E97E401}.z3apidebug|x86.ActiveCfg = z3apidebug|Any CPU
- {A598ED5A-93AD-4125-A555-3921A2F936FA}.Checked|Any CPU.ActiveCfg = Checked|Any CPU
- {A598ED5A-93AD-4125-A555-3921A2F936FA}.Checked|Any CPU.Build.0 = Checked|Any CPU
- {A598ED5A-93AD-4125-A555-3921A2F936FA}.Checked|Mixed Platforms.ActiveCfg = Checked|Any CPU
- {A598ED5A-93AD-4125-A555-3921A2F936FA}.Checked|Mixed Platforms.Build.0 = Checked|Any CPU
- {A598ED5A-93AD-4125-A555-3921A2F936FA}.Checked|x86.ActiveCfg = Checked|Any CPU
- {A598ED5A-93AD-4125-A555-3921A2F936FA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {A598ED5A-93AD-4125-A555-3921A2F936FA}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {A598ED5A-93AD-4125-A555-3921A2F936FA}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
- {A598ED5A-93AD-4125-A555-3921A2F936FA}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
- {A598ED5A-93AD-4125-A555-3921A2F936FA}.Debug|x86.ActiveCfg = Debug|Any CPU
- {A598ED5A-93AD-4125-A555-3921A2F936FA}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {A598ED5A-93AD-4125-A555-3921A2F936FA}.Release|Any CPU.Build.0 = Release|Any CPU
- {A598ED5A-93AD-4125-A555-3921A2F936FA}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
- {A598ED5A-93AD-4125-A555-3921A2F936FA}.Release|Mixed Platforms.Build.0 = Release|Any CPU
- {A598ED5A-93AD-4125-A555-3921A2F936FA}.Release|x86.ActiveCfg = Release|Any CPU
- {A598ED5A-93AD-4125-A555-3921A2F936FA}.z3apidebug|Any CPU.ActiveCfg = Checked|Any CPU
- {A598ED5A-93AD-4125-A555-3921A2F936FA}.z3apidebug|Any CPU.Build.0 = Checked|Any CPU
- {A598ED5A-93AD-4125-A555-3921A2F936FA}.z3apidebug|Mixed Platforms.ActiveCfg = Checked|Any CPU
- {A598ED5A-93AD-4125-A555-3921A2F936FA}.z3apidebug|Mixed Platforms.Build.0 = Checked|Any CPU
- {A598ED5A-93AD-4125-A555-3921A2F936FA}.z3apidebug|x86.ActiveCfg = Checked|Any CPU
- {FEE9F01B-9722-4A76-A24B-72A4016DFA8E}.Checked|Any CPU.ActiveCfg = Checked|Any CPU
- {FEE9F01B-9722-4A76-A24B-72A4016DFA8E}.Checked|Any CPU.Build.0 = Checked|Any CPU
- {FEE9F01B-9722-4A76-A24B-72A4016DFA8E}.Checked|Mixed Platforms.ActiveCfg = Checked|Any CPU
- {FEE9F01B-9722-4A76-A24B-72A4016DFA8E}.Checked|Mixed Platforms.Build.0 = Checked|Any CPU
- {FEE9F01B-9722-4A76-A24B-72A4016DFA8E}.Checked|x86.ActiveCfg = Checked|Any CPU
- {FEE9F01B-9722-4A76-A24B-72A4016DFA8E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {FEE9F01B-9722-4A76-A24B-72A4016DFA8E}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {FEE9F01B-9722-4A76-A24B-72A4016DFA8E}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
- {FEE9F01B-9722-4A76-A24B-72A4016DFA8E}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
- {FEE9F01B-9722-4A76-A24B-72A4016DFA8E}.Debug|x86.ActiveCfg = Debug|Any CPU
- {FEE9F01B-9722-4A76-A24B-72A4016DFA8E}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {FEE9F01B-9722-4A76-A24B-72A4016DFA8E}.Release|Any CPU.Build.0 = Release|Any CPU
- {FEE9F01B-9722-4A76-A24B-72A4016DFA8E}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
- {FEE9F01B-9722-4A76-A24B-72A4016DFA8E}.Release|Mixed Platforms.Build.0 = Release|Any CPU
- {FEE9F01B-9722-4A76-A24B-72A4016DFA8E}.Release|x86.ActiveCfg = Release|Any CPU
- {FEE9F01B-9722-4A76-A24B-72A4016DFA8E}.z3apidebug|Any CPU.ActiveCfg = z3apidebug|Any CPU
- {FEE9F01B-9722-4A76-A24B-72A4016DFA8E}.z3apidebug|Any CPU.Build.0 = z3apidebug|Any CPU
- {FEE9F01B-9722-4A76-A24B-72A4016DFA8E}.z3apidebug|Mixed Platforms.ActiveCfg = z3apidebug|Any CPU
- {FEE9F01B-9722-4A76-A24B-72A4016DFA8E}.z3apidebug|Mixed Platforms.Build.0 = z3apidebug|Any CPU
- {FEE9F01B-9722-4A76-A24B-72A4016DFA8E}.z3apidebug|x86.ActiveCfg = z3apidebug|Any CPU
{E1F10180-C7B9-4147-B51F-FA1B701966DC}.Checked|Any CPU.ActiveCfg = Checked|Any CPU
{E1F10180-C7B9-4147-B51F-FA1B701966DC}.Checked|Any CPU.Build.0 = Checked|Any CPU
{E1F10180-C7B9-4147-B51F-FA1B701966DC}.Checked|Mixed Platforms.ActiveCfg = Checked|Any CPU
@@ -415,6 +329,26 @@ Global
{56FFDBCA-7D14-43B8-A6CA-22A20E417EE1}.z3apidebug|Mixed Platforms.ActiveCfg = z3apidebug|Any CPU
{56FFDBCA-7D14-43B8-A6CA-22A20E417EE1}.z3apidebug|Mixed Platforms.Build.0 = z3apidebug|Any CPU
{56FFDBCA-7D14-43B8-A6CA-22A20E417EE1}.z3apidebug|x86.ActiveCfg = z3apidebug|Any CPU
+ {435D5BD0-6F62-49F8-BB24-33E2257519AD}.Checked|Any CPU.ActiveCfg = Checked|Any CPU
+ {435D5BD0-6F62-49F8-BB24-33E2257519AD}.Checked|Any CPU.Build.0 = Checked|Any CPU
+ {435D5BD0-6F62-49F8-BB24-33E2257519AD}.Checked|Mixed Platforms.ActiveCfg = Checked|Any CPU
+ {435D5BD0-6F62-49F8-BB24-33E2257519AD}.Checked|Mixed Platforms.Build.0 = Checked|Any CPU
+ {435D5BD0-6F62-49F8-BB24-33E2257519AD}.Checked|x86.ActiveCfg = Checked|Any CPU
+ {435D5BD0-6F62-49F8-BB24-33E2257519AD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {435D5BD0-6F62-49F8-BB24-33E2257519AD}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {435D5BD0-6F62-49F8-BB24-33E2257519AD}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {435D5BD0-6F62-49F8-BB24-33E2257519AD}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {435D5BD0-6F62-49F8-BB24-33E2257519AD}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {435D5BD0-6F62-49F8-BB24-33E2257519AD}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {435D5BD0-6F62-49F8-BB24-33E2257519AD}.Release|Any CPU.Build.0 = Release|Any CPU
+ {435D5BD0-6F62-49F8-BB24-33E2257519AD}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {435D5BD0-6F62-49F8-BB24-33E2257519AD}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {435D5BD0-6F62-49F8-BB24-33E2257519AD}.Release|x86.ActiveCfg = Release|Any CPU
+ {435D5BD0-6F62-49F8-BB24-33E2257519AD}.z3apidebug|Any CPU.ActiveCfg = z3apidebug|Any CPU
+ {435D5BD0-6F62-49F8-BB24-33E2257519AD}.z3apidebug|Any CPU.Build.0 = z3apidebug|Any CPU
+ {435D5BD0-6F62-49F8-BB24-33E2257519AD}.z3apidebug|Mixed Platforms.ActiveCfg = z3apidebug|Any CPU
+ {435D5BD0-6F62-49F8-BB24-33E2257519AD}.z3apidebug|Mixed Platforms.Build.0 = z3apidebug|Any CPU
+ {435D5BD0-6F62-49F8-BB24-33E2257519AD}.z3apidebug|x86.ActiveCfg = z3apidebug|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/Source/GPUVerify/AccessInvariantProcessor.cs b/Source/GPUVerify/AccessInvariantProcessor.cs
new file mode 100644
index 00000000..4a5c34e8
--- /dev/null
+++ b/Source/GPUVerify/AccessInvariantProcessor.cs
@@ -0,0 +1,107 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Microsoft.Boogie;
+using System.Diagnostics;
+
+namespace GPUVerify
+{
+ class AccessInvariantProcessor : StandardVisitor
+ {
+
+ private const string NO_READ = "__no_read_";
+ private const string NO_WRITE = "__no_write_";
+ private const string READ = "__read_";
+ private const string WRITE = "__write_";
+ private const string READ_OFFSET = "__read_offset_";
+ private const string WRITE_OFFSET = "__write_offset_";
+ private const string READ_IMPLIES = "__read_implies_";
+ private const string WRITE_IMPLIES = "__write_implies_";
+
+ public override Expr VisitNAryExpr(NAryExpr node)
+ {
+
+ if (node.Fun is FunctionCall)
+ {
+ FunctionCall call = node.Fun as FunctionCall;
+
+ if (MatchesIntrinsic(call.Func, NO_READ))
+ {
+ return Expr.Not(
+ MakeReadHasOccurred(node, call, NO_READ)
+ );
+ }
+
+ if (MatchesIntrinsic(call.Func, NO_WRITE))
+ {
+ return Expr.Not(
+ MakeWriteHasOccurred(node, call, NO_WRITE)
+ );
+ }
+
+ if (MatchesIntrinsic(call.Func, READ_OFFSET))
+ {
+ return new IdentifierExpr(node.tok, new GlobalVariable(
+ node.tok, new TypedIdent(node.tok, "_READ_OFFSET_X_" +
+ call.Func.Name.Substring(READ_OFFSET.Length), Microsoft.Boogie.Type.GetBvType(32)))
+ );
+ }
+
+ if (MatchesIntrinsic(call.Func, WRITE_OFFSET))
+ {
+ return new IdentifierExpr(node.tok, new GlobalVariable(
+ node.tok, new TypedIdent(node.tok, "_WRITE_OFFSET_X_" +
+ call.Func.Name.Substring(WRITE_OFFSET.Length), Microsoft.Boogie.Type.GetBvType(32)))
+ );
+ }
+
+ if (MatchesIntrinsic(call.Func, READ))
+ {
+ return MakeReadHasOccurred(node, call, READ);
+ }
+
+ if (MatchesIntrinsic(call.Func, WRITE))
+ {
+ return MakeWriteHasOccurred(node, call, WRITE);
+ }
+
+ if (MatchesIntrinsic(call.Func, READ_IMPLIES))
+ {
+ return Expr.Imp(MakeReadHasOccurred(node, call, READ_IMPLIES), node.Args[0]);
+ }
+
+ if (MatchesIntrinsic(call.Func, WRITE_IMPLIES))
+ {
+ return Expr.Imp(MakeWriteHasOccurred(node, call, WRITE_IMPLIES), node.Args[0]);
+ }
+
+ }
+
+ return base.VisitNAryExpr(node);
+ }
+
+ private static IdentifierExpr MakeReadHasOccurred(NAryExpr node, FunctionCall call, string intrinsicPrefix)
+ {
+ return new IdentifierExpr(node.tok, new GlobalVariable(
+ node.tok, new TypedIdent(node.tok, "_READ_HAS_OCCURRED_" +
+ call.Func.Name.Substring(intrinsicPrefix.Length), Microsoft.Boogie.Type.Bool)));
+ }
+
+ private static IdentifierExpr MakeWriteHasOccurred(NAryExpr node, FunctionCall call, string intrinsicPrefix)
+ {
+ return new IdentifierExpr(node.tok, new GlobalVariable(
+ node.tok, new TypedIdent(node.tok, "_WRITE_HAS_OCCURRED_" +
+ call.Func.Name.Substring(intrinsicPrefix.Length), Microsoft.Boogie.Type.Bool)));
+ }
+
+
+ private bool MatchesIntrinsic(Function function, string intrinsicPrefix)
+ {
+ return function.Name.Length > intrinsicPrefix.Length &&
+ function.Name.Substring(0, intrinsicPrefix.Length).Equals(intrinsicPrefix);
+ }
+
+
+ }
+}
diff --git a/Source/GPUVerify/AsymmetricExpressionFinder.cs b/Source/GPUVerify/AsymmetricExpressionFinder.cs
new file mode 100644
index 00000000..40c7eb32
--- /dev/null
+++ b/Source/GPUVerify/AsymmetricExpressionFinder.cs
@@ -0,0 +1,29 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Microsoft.Boogie;
+
+namespace GPUVerify
+{
+ class AsymmetricExpressionFinder : StandardVisitor
+ {
+ private bool found = false;
+
+ internal bool foundAsymmetricExpr()
+ {
+ return found;
+ }
+
+ public override Variable VisitVariable(Variable node)
+ {
+ if (node.TypedIdent.Name.Contains("_READ_HAS_OCCURRED") ||
+ node.TypedIdent.Name.Contains("_READ_OFFSET"))
+ {
+ found = true;
+ }
+ return node;
+ }
+
+ }
+}
diff --git a/Source/GPUVerify/CrossThreadInvariantProcessor.cs b/Source/GPUVerify/CrossThreadInvariantProcessor.cs
new file mode 100644
index 00000000..c9b4c26c
--- /dev/null
+++ b/Source/GPUVerify/CrossThreadInvariantProcessor.cs
@@ -0,0 +1,53 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Microsoft.Boogie;
+using System.Diagnostics;
+
+namespace GPUVerify
+{
+ class CrossThreadInvariantProcessor : StandardVisitor
+ {
+
+ public override Expr VisitNAryExpr(NAryExpr node)
+ {
+
+ if (node.Fun is FunctionCall)
+ {
+ FunctionCall call = node.Fun as FunctionCall;
+
+ if (call.Func.Name.Equals("__uniform_bv32") || call.Func.Name.Equals("__uniform_bool"))
+ {
+ return Expr.Eq(new VariableDualiser(1).VisitExpr(node.Args[0].Clone() as Expr),
+ new VariableDualiser(2).VisitExpr(node.Args[0].Clone() as Expr));
+ }
+
+ if (call.Func.Name.Equals("__distinct_bv32") || call.Func.Name.Equals("__distinct_bool"))
+ {
+ return Expr.Neq(new VariableDualiser(1).VisitExpr(node.Args[0].Clone() as Expr),
+ new VariableDualiser(2).VisitExpr(node.Args[0].Clone() as Expr));
+ }
+
+ if (call.Func.Name.Equals("__all"))
+ {
+ return Expr.And(new VariableDualiser(1).VisitExpr(node.Args[0].Clone() as Expr),
+ new VariableDualiser(2).VisitExpr(node.Args[0].Clone() as Expr));
+ }
+
+ if (call.Func.Name.Equals("__at_most_one"))
+ {
+ return Expr.Not(Expr.And(new VariableDualiser(1).VisitExpr(node.Args[0].Clone() as Expr),
+ new VariableDualiser(2).VisitExpr(node.Args[0].Clone() as Expr)));
+ }
+
+
+ }
+
+ return base.VisitNAryExpr(node);
+ }
+
+
+
+ }
+}
diff --git a/Source/GPUVerify/ElementEncodingRaceInstrumenter.cs b/Source/GPUVerify/ElementEncodingRaceInstrumenter.cs
index 84624e5d..103974ec 100644
--- a/Source/GPUVerify/ElementEncodingRaceInstrumenter.cs
+++ b/Source/GPUVerify/ElementEncodingRaceInstrumenter.cs
@@ -191,46 +191,46 @@ namespace GPUVerify
bb.simpleCmds.Add(new AssignCmd(tok, lhss, rhss));
}
- public override void CheckForRaces(IToken tok, BigBlock bb, Variable v, bool ReadWriteOnly)
+ public override void CheckForRaces(BigBlock bb, Variable v, bool ReadWriteOnly)
{
if (!ReadWriteOnly)
{
- bb.simpleCmds.Add(new AssertCmd(tok, Expr.Not(GenerateRaceCondition(tok, v, "WRITE", "WRITE"))));
+ bb.simpleCmds.Add(new AssertCmd(v.tok, Expr.Not(GenerateRaceCondition(v, "WRITE", "WRITE"))));
}
- bb.simpleCmds.Add(new AssertCmd(tok, Expr.Not(GenerateRaceCondition(tok, v, "READ", "WRITE"))));
+ bb.simpleCmds.Add(new AssertCmd(v.tok, Expr.Not(GenerateRaceCondition(v, "READ", "WRITE"))));
if (!CommandLineOptions.Symmetry)
{
- bb.simpleCmds.Add(new AssertCmd(tok, Expr.Not(GenerateRaceCondition(tok, v, "WRITE", "READ"))));
+ bb.simpleCmds.Add(new AssertCmd(v.tok, Expr.Not(GenerateRaceCondition(v, "WRITE", "READ"))));
}
}
- private static Expr GenerateRaceCondition(IToken tok, Variable v, string FirstAccessType, string SecondAccessType)
+ protected override Expr GenerateRaceCondition(Variable v, string FirstAccessType, string SecondAccessType)
{
Expr RaceCondition = Expr.And(
- new IdentifierExpr(tok, new VariableDualiser(1).VisitVariable(MakeReadOrWriteHasOccurredVariable(v, FirstAccessType))),
- new IdentifierExpr(tok, new VariableDualiser(2).VisitVariable(MakeReadOrWriteHasOccurredVariable(v, SecondAccessType))));
+ new IdentifierExpr(v.tok, new VariableDualiser(1).VisitVariable(MakeReadOrWriteHasOccurredVariable(v, FirstAccessType))),
+ new IdentifierExpr(v.tok, new VariableDualiser(2).VisitVariable(MakeReadOrWriteHasOccurredVariable(v, SecondAccessType))));
if (GPUVerifier.HasXDimension(v))
{
RaceCondition = Expr.And(RaceCondition, Expr.Eq(
- new IdentifierExpr(tok, new VariableDualiser(1).VisitVariable(GPUVerifier.MakeOffsetXVariable(v, FirstAccessType))),
- new IdentifierExpr(tok, new VariableDualiser(2).VisitVariable(GPUVerifier.MakeOffsetXVariable(v, SecondAccessType)))
+ new IdentifierExpr(v.tok, new VariableDualiser(1).VisitVariable(GPUVerifier.MakeOffsetXVariable(v, FirstAccessType))),
+ new IdentifierExpr(v.tok, new VariableDualiser(2).VisitVariable(GPUVerifier.MakeOffsetXVariable(v, SecondAccessType)))
));
}
if (GPUVerifier.HasYDimension(v))
{
RaceCondition = Expr.And(RaceCondition, Expr.Eq(
- new IdentifierExpr(tok, new VariableDualiser(1).VisitVariable(GPUVerifier.MakeOffsetYVariable(v, FirstAccessType))),
- new IdentifierExpr(tok, new VariableDualiser(2).VisitVariable(GPUVerifier.MakeOffsetYVariable(v, SecondAccessType)))
+ new IdentifierExpr(v.tok, new VariableDualiser(1).VisitVariable(GPUVerifier.MakeOffsetYVariable(v, FirstAccessType))),
+ new IdentifierExpr(v.tok, new VariableDualiser(2).VisitVariable(GPUVerifier.MakeOffsetYVariable(v, SecondAccessType)))
));
}
if (GPUVerifier.HasZDimension(v))
{
RaceCondition = Expr.And(RaceCondition, Expr.Eq(
- new IdentifierExpr(tok, new VariableDualiser(1).VisitVariable(GPUVerifier.MakeOffsetZVariable(v, FirstAccessType))),
- new IdentifierExpr(tok, new VariableDualiser(2).VisitVariable(GPUVerifier.MakeOffsetZVariable(v, SecondAccessType)))
+ new IdentifierExpr(v.tok, new VariableDualiser(1).VisitVariable(GPUVerifier.MakeOffsetZVariable(v, FirstAccessType))),
+ new IdentifierExpr(v.tok, new VariableDualiser(2).VisitVariable(GPUVerifier.MakeOffsetZVariable(v, SecondAccessType)))
));
}
diff --git a/Source/GPUVerify/EnabledToPredicateVisitor.cs b/Source/GPUVerify/EnabledToPredicateVisitor.cs
new file mode 100644
index 00000000..3cedd075
--- /dev/null
+++ b/Source/GPUVerify/EnabledToPredicateVisitor.cs
@@ -0,0 +1,39 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Microsoft.Boogie;
+using System.Diagnostics;
+
+namespace GPUVerify
+{
+ class EnabledToPredicateVisitor : StandardVisitor
+ {
+
+ public EnabledToPredicateVisitor(TypedIdent currentPredicate)
+ {
+ this.currentPredicate = currentPredicate;
+
+ }
+
+ private TypedIdent currentPredicate;
+
+
+ public override Expr VisitNAryExpr(NAryExpr node)
+ {
+ if (node.Fun is FunctionCall)
+ {
+ FunctionCall call = node.Fun as FunctionCall;
+
+ if (call.Func.Name.Equals("__enabled"))
+ {
+ return new IdentifierExpr(node.tok, new LocalVariable(node.tok, currentPredicate));
+ }
+
+ }
+
+ return base.VisitNAryExpr(node);
+ }
+
+ }
+}
diff --git a/Source/GPUVerify/GPUVerifier.cs b/Source/GPUVerify/GPUVerifier.cs
index 2f9be79b..86938ab2 100644
--- a/Source/GPUVerify/GPUVerifier.cs
+++ b/Source/GPUVerify/GPUVerifier.cs
@@ -310,6 +310,8 @@ namespace GPUVerify
return;
}
+ ProcessAccessInvariants();
+
if (CommandLineOptions.ShowStages)
{
emitProgram(outputFilename + "_instrumented");
@@ -336,6 +338,13 @@ namespace GPUVerify
emitProgram(outputFilename + "_dualised");
}
+ ProcessCrossThreadInvariants();
+
+ if (CommandLineOptions.ShowStages)
+ {
+ emitProgram(outputFilename + "_cross_thread_invariants");
+ }
+
if (CommandLineOptions.Eager)
{
AddEagerRaceChecking();
@@ -343,7 +352,7 @@ namespace GPUVerify
GenerateBarrierImplementation();
- GenerateKernelPrecondition();
+ GenerateStandardKernelContract();
if (CommandLineOptions.ShowStages)
{
@@ -399,6 +408,186 @@ namespace GPUVerify
}
+ private void ProcessAccessInvariants()
+ {
+ foreach (Declaration d in Program.TopLevelDeclarations)
+ {
+ if (d is Procedure)
+ {
+ Procedure p = d as Procedure;
+ p.Requires = ProcessAccessInvariants(p.Requires);
+ p.Ensures = ProcessAccessInvariants(p.Ensures);
+ }
+
+ if (d is Implementation)
+ {
+ Implementation i = d as Implementation;
+ ProcessAccessInvariants(i.StructuredStmts);
+ }
+ }
+ }
+
+ private void ProcessAccessInvariants(StmtList stmtList)
+ {
+
+ foreach (BigBlock bb in stmtList.BigBlocks)
+ {
+ ProcessAccessInvariants(bb);
+ }
+ }
+
+ private void ProcessAccessInvariants(BigBlock bb)
+ {
+ CmdSeq newCommands = new CmdSeq();
+
+ foreach (Cmd c in bb.simpleCmds)
+ {
+ if (c is AssertCmd)
+ {
+ newCommands.Add(new AssertCmd(c.tok, new AccessInvariantProcessor().VisitExpr((c as AssertCmd).Expr.Clone() as Expr)));
+ }
+ else if (c is AssumeCmd)
+ {
+ newCommands.Add(new AssumeCmd(c.tok, new AccessInvariantProcessor().VisitExpr((c as AssumeCmd).Expr.Clone() as Expr)));
+ }
+ else
+ {
+ newCommands.Add(c);
+ }
+ }
+
+ bb.simpleCmds = newCommands;
+
+ if (bb.ec is WhileCmd)
+ {
+ WhileCmd whileCmd = bb.ec as WhileCmd;
+ whileCmd.Invariants = ProcessAccessInvariants(whileCmd.Invariants);
+ ProcessAccessInvariants(whileCmd.Body);
+ }
+ else if (bb.ec is IfCmd)
+ {
+ ProcessAccessInvariants((bb.ec as IfCmd).thn);
+ if ((bb.ec as IfCmd).elseBlock != null)
+ {
+ ProcessAccessInvariants((bb.ec as IfCmd).elseBlock);
+ }
+ }
+ }
+
+ private List<PredicateCmd> ProcessAccessInvariants(List<PredicateCmd> invariants)
+ {
+ List<PredicateCmd> result = new List<PredicateCmd>();
+
+ foreach (PredicateCmd p in invariants)
+ {
+ result.Add(new AssertCmd(p.tok, new AccessInvariantProcessor().VisitExpr(p.Expr.Clone() as Expr)));
+ }
+
+ return result;
+ }
+
+ private EnsuresSeq ProcessAccessInvariants(EnsuresSeq ensuresSeq)
+ {
+ EnsuresSeq result = new EnsuresSeq();
+ foreach (Ensures e in ensuresSeq)
+ {
+ result.Add(new Ensures(e.Free, new AccessInvariantProcessor().VisitExpr(e.Condition.Clone() as Expr)));
+ }
+ return result;
+ }
+
+ private RequiresSeq ProcessAccessInvariants(RequiresSeq requiresSeq)
+ {
+ RequiresSeq result = new RequiresSeq();
+ foreach (Requires r in requiresSeq)
+ {
+ result.Add(new Requires(r.Free, new AccessInvariantProcessor().VisitExpr(r.Condition.Clone() as Expr)));
+ }
+ return result;
+ }
+
+ private void ProcessCrossThreadInvariants()
+ {
+ foreach (Declaration d in Program.TopLevelDeclarations)
+ {
+ if (d is Procedure)
+ {
+ Procedure p = d as Procedure;
+ p.Requires = ProcessCrossThreadInvariants(p.Requires);
+ p.Ensures = ProcessCrossThreadInvariants(p.Ensures);
+ }
+ if (d is Implementation)
+ {
+ Implementation i = d as Implementation;
+ ProcessCrossThreadInvariants(i.StructuredStmts);
+ }
+
+ }
+ }
+
+ private EnsuresSeq ProcessCrossThreadInvariants(EnsuresSeq ensuresSeq)
+ {
+ EnsuresSeq result = new EnsuresSeq();
+ foreach (Ensures e in ensuresSeq)
+ {
+ result.Add(new Ensures(e.Free, new CrossThreadInvariantProcessor().VisitExpr(e.Condition.Clone() as Expr)));
+ }
+ return result;
+ }
+
+ private RequiresSeq ProcessCrossThreadInvariants(RequiresSeq requiresSeq)
+ {
+ RequiresSeq result = new RequiresSeq();
+ foreach (Requires r in requiresSeq)
+ {
+ result.Add(new Requires(r.Free, new CrossThreadInvariantProcessor().VisitExpr(r.Condition.Clone() as Expr)));
+ }
+ return result;
+ }
+
+ private void ProcessCrossThreadInvariants(StmtList stmtList)
+ {
+ foreach (BigBlock bb in stmtList.BigBlocks)
+ {
+ ProcessCrossThreadInvariants(bb);
+ }
+ }
+
+ private void ProcessCrossThreadInvariants(BigBlock bb)
+ {
+ CmdSeq newCommands = new CmdSeq();
+
+ foreach (Cmd c in bb.simpleCmds)
+ {
+ if (c is AssertCmd)
+ {
+ newCommands.Add(new AssertCmd(c.tok, new CrossThreadInvariantProcessor().VisitExpr((c as AssertCmd).Expr.Clone() as Expr)));
+ }
+ else if (c is AssumeCmd)
+ {
+ newCommands.Add(new AssumeCmd(c.tok, new CrossThreadInvariantProcessor().VisitExpr((c as AssumeCmd).Expr.Clone() as Expr)));
+ }
+ else
+ {
+ newCommands.Add(c);
+ }
+ }
+
+ bb.simpleCmds = newCommands;
+
+ if (bb.ec is WhileCmd)
+ {
+ WhileCmd whileCmd = bb.ec as WhileCmd;
+ List<PredicateCmd> newInvariants = new List<PredicateCmd>();
+ foreach(PredicateCmd p in whileCmd.Invariants)
+ {
+ newInvariants.Add(new AssertCmd(p.tok, new CrossThreadInvariantProcessor().VisitExpr(p.Expr)));
+ }
+ whileCmd.Invariants = newInvariants;
+ ProcessCrossThreadInvariants(whileCmd.Body);
+ }
+ }
+
private void emitProgram(string filename)
{
using (TokenTextWriter writer = new TokenTextWriter(filename + ".bpl"))
@@ -423,7 +612,7 @@ namespace GPUVerify
if (impl.Name.Equals("_LOG_READ_" + v.Name) || impl.Name.Equals("_LOG_WRITE_" + v.Name))
{
BigBlock bb = new BigBlock(v.tok, "__CheckForRaces", new CmdSeq(), null, null);
- RaceInstrumenter.CheckForRaces(v.tok, bb, v, impl.Name.Equals("_LOG_READ_" + v.Name));
+ RaceInstrumenter.CheckForRaces(bb, v, impl.Name.Equals("_LOG_READ_" + v.Name));
StmtList newStatements = new StmtList(new List<BigBlock>(), v.tok);
foreach(BigBlock bb2 in impl.StructuredStmts.BigBlocks)
@@ -936,18 +1125,6 @@ namespace GPUVerify
return _GROUP_SIZE_Z != null;
}
- public bool KernelHasId(string dimension)
- {
- Contract.Requires(dimension.Equals("X") || dimension.Equals("Y") || dimension.Equals("Z"));
- if (dimension.Equals("X")) return KernelHasIdX();
- if (dimension.Equals("Y")) return KernelHasIdY();
- if (dimension.Equals("Z")) return KernelHasIdZ();
- Debug.Assert(false);
- return false;
- }
-
-
-
public void AddCandidateInvariant(WhileCmd wc, Expr e)
{
Constant ExistentialBooleanConstant = MakeExistentialBoolean(wc.tok);
@@ -989,7 +1166,7 @@ namespace GPUVerify
KernelImplementation.StructuredStmts.BigBlocks.Add(bb);
}
- private void GenerateKernelPrecondition()
+ private void GenerateStandardKernelContract()
{
RaceInstrumenter.AddKernelPrecondition();
@@ -1019,6 +1196,12 @@ namespace GPUVerify
Proc.Requires.Add(new Requires(false, AssumeDistinctThreads));
Proc.Requires.Add(new Requires(false, AssumeThreadIdsInRange));
+
+ if (Proc != KernelProcedure)
+ {
+ RaceInstrumenter.AddNoRaceContract(Proc);
+ }
+
}
}
else
@@ -1033,6 +1216,9 @@ namespace GPUVerify
continue;
}
Implementation Impl = D as Implementation;
+
+ RaceInstrumenter.AddNoRaceInvariants(Impl);
+
if (QKeyValue.FindIntAttribute(Impl.Proc.Attributes, "inline", -1) == 1)
{
continue;
@@ -1138,68 +1324,65 @@ namespace GPUVerify
private void GeneratePreconditionsForDimension(ref Expr AssumeDistinctThreads, ref Expr AssumeThreadIdsInRange, IToken tok, String dimension)
{
- if (KernelHasId(dimension))
+ foreach (Declaration D in Program.TopLevelDeclarations)
{
- foreach (Declaration D in Program.TopLevelDeclarations)
+ if (!(D is Procedure))
{
- if (!(D is Procedure))
- {
- continue;
- }
- Procedure Proc = D as Procedure;
- if (QKeyValue.FindIntAttribute(Proc.Attributes, "inline", -1) == 1)
- {
- continue;
- }
+ continue;
+ }
+ Procedure Proc = D as Procedure;
+ if (QKeyValue.FindIntAttribute(Proc.Attributes, "inline", -1) == 1)
+ {
+ continue;
+ }
- if (GetTypeOfId(dimension).Equals(Microsoft.Boogie.Type.GetBvType(32)))
- {
- Proc.Requires.Add(new Requires(false, MakeBitVectorBinaryBoolean("BV32_GT", new IdentifierExpr(tok, GetGroupSize(dimension)), ZeroBV(tok))));
- Proc.Requires.Add(new Requires(false, MakeBitVectorBinaryBoolean("BV32_GT", new IdentifierExpr(tok, GetNumGroups(dimension)), ZeroBV(tok))));
- Proc.Requires.Add(new Requires(false, MakeBitVectorBinaryBoolean("BV32_GEQ", new IdentifierExpr(tok, GetGroupId(dimension)), ZeroBV(tok))));
- Proc.Requires.Add(new Requires(false, MakeBitVectorBinaryBoolean("BV32_LT", new IdentifierExpr(tok, GetGroupId(dimension)), new IdentifierExpr(tok, GetNumGroups(dimension)))));
- }
- else
- {
- Proc.Requires.Add(new Requires(false, Expr.Gt(new IdentifierExpr(tok, GetGroupSize(dimension)), Zero(tok))));
- Proc.Requires.Add(new Requires(false, Expr.Gt(new IdentifierExpr(tok, GetNumGroups(dimension)), Zero(tok))));
- Proc.Requires.Add(new Requires(false, Expr.Ge(new IdentifierExpr(tok, GetGroupId(dimension)), Zero(tok))));
- Proc.Requires.Add(new Requires(false, Expr.Lt(new IdentifierExpr(tok, GetGroupId(dimension)), new IdentifierExpr(tok, GetNumGroups(dimension)))));
- }
+ if (GetTypeOfId(dimension).Equals(Microsoft.Boogie.Type.GetBvType(32)))
+ {
+ Proc.Requires.Add(new Requires(false, MakeBitVectorBinaryBoolean("BV32_GT", new IdentifierExpr(tok, GetGroupSize(dimension)), ZeroBV(tok))));
+ Proc.Requires.Add(new Requires(false, MakeBitVectorBinaryBoolean("BV32_GT", new IdentifierExpr(tok, GetNumGroups(dimension)), ZeroBV(tok))));
+ Proc.Requires.Add(new Requires(false, MakeBitVectorBinaryBoolean("BV32_GEQ", new IdentifierExpr(tok, GetGroupId(dimension)), ZeroBV(tok))));
+ Proc.Requires.Add(new Requires(false, MakeBitVectorBinaryBoolean("BV32_LT", new IdentifierExpr(tok, GetGroupId(dimension)), new IdentifierExpr(tok, GetNumGroups(dimension)))));
}
+ else
+ {
+ Proc.Requires.Add(new Requires(false, Expr.Gt(new IdentifierExpr(tok, GetGroupSize(dimension)), Zero(tok))));
+ Proc.Requires.Add(new Requires(false, Expr.Gt(new IdentifierExpr(tok, GetNumGroups(dimension)), Zero(tok))));
+ Proc.Requires.Add(new Requires(false, Expr.Ge(new IdentifierExpr(tok, GetGroupId(dimension)), Zero(tok))));
+ Proc.Requires.Add(new Requires(false, Expr.Lt(new IdentifierExpr(tok, GetGroupId(dimension)), new IdentifierExpr(tok, GetNumGroups(dimension)))));
+ }
+ }
- Expr AssumeThreadsDistinctInDimension =
- Expr.Neq(
- new IdentifierExpr(tok, MakeThreadId(tok, dimension, 1)),
- new IdentifierExpr(tok, MakeThreadId(tok, dimension, 2))
- );
+ Expr AssumeThreadsDistinctInDimension =
+ Expr.Neq(
+ new IdentifierExpr(tok, MakeThreadId(tok, dimension, 1)),
+ new IdentifierExpr(tok, MakeThreadId(tok, dimension, 2))
+ );
- AssumeDistinctThreads = (null == AssumeDistinctThreads) ? AssumeThreadsDistinctInDimension : Expr.Or(AssumeDistinctThreads, AssumeThreadsDistinctInDimension);
+ AssumeDistinctThreads = (null == AssumeDistinctThreads) ? AssumeThreadsDistinctInDimension : Expr.Or(AssumeDistinctThreads, AssumeThreadsDistinctInDimension);
- Expr AssumeThreadIdsInRangeInDimension =
- GetTypeOfId(dimension).Equals(Microsoft.Boogie.Type.GetBvType(32)) ?
+ Expr AssumeThreadIdsInRangeInDimension =
+ GetTypeOfId(dimension).Equals(Microsoft.Boogie.Type.GetBvType(32)) ?
+ Expr.And(
Expr.And(
- Expr.And(
- MakeBitVectorBinaryBoolean("BV32_GEQ", new IdentifierExpr(tok, MakeThreadId(tok, dimension, 1)), ZeroBV(tok)),
- MakeBitVectorBinaryBoolean("BV32_GEQ", new IdentifierExpr(tok, MakeThreadId(tok, dimension, 2)), ZeroBV(tok))
- ),
- Expr.And(
- MakeBitVectorBinaryBoolean("BV32_LT", new IdentifierExpr(tok, MakeThreadId(tok, dimension, 1)), new IdentifierExpr(tok, GetGroupSize(dimension))),
- MakeBitVectorBinaryBoolean("BV32_LT", new IdentifierExpr(tok, MakeThreadId(tok, dimension, 2)), new IdentifierExpr(tok, GetGroupSize(dimension)))
- ))
- :
+ MakeBitVectorBinaryBoolean("BV32_GEQ", new IdentifierExpr(tok, MakeThreadId(tok, dimension, 1)), ZeroBV(tok)),
+ MakeBitVectorBinaryBoolean("BV32_GEQ", new IdentifierExpr(tok, MakeThreadId(tok, dimension, 2)), ZeroBV(tok))
+ ),
Expr.And(
- Expr.And(
- Expr.Ge(new IdentifierExpr(tok, MakeThreadId(tok, dimension, 1)), Zero(tok)),
- Expr.Ge(new IdentifierExpr(tok, MakeThreadId(tok, dimension, 2)), Zero(tok))
- ),
- Expr.And(
- Expr.Lt(new IdentifierExpr(tok, MakeThreadId(tok, dimension, 1)), new IdentifierExpr(tok, GetGroupSize(dimension))),
- Expr.Lt(new IdentifierExpr(tok, MakeThreadId(tok, dimension, 2)), new IdentifierExpr(tok, GetGroupSize(dimension)))
- ));
+ MakeBitVectorBinaryBoolean("BV32_LT", new IdentifierExpr(tok, MakeThreadId(tok, dimension, 1)), new IdentifierExpr(tok, GetGroupSize(dimension))),
+ MakeBitVectorBinaryBoolean("BV32_LT", new IdentifierExpr(tok, MakeThreadId(tok, dimension, 2)), new IdentifierExpr(tok, GetGroupSize(dimension)))
+ ))
+ :
+ Expr.And(
+ Expr.And(
+ Expr.Ge(new IdentifierExpr(tok, MakeThreadId(tok, dimension, 1)), Zero(tok)),
+ Expr.Ge(new IdentifierExpr(tok, MakeThreadId(tok, dimension, 2)), Zero(tok))
+ ),
+ Expr.And(
+ Expr.Lt(new IdentifierExpr(tok, MakeThreadId(tok, dimension, 1)), new IdentifierExpr(tok, GetGroupSize(dimension))),
+ Expr.Lt(new IdentifierExpr(tok, MakeThreadId(tok, dimension, 2)), new IdentifierExpr(tok, GetGroupSize(dimension)))
+ ));
- AssumeThreadIdsInRange = (null == AssumeThreadIdsInRange) ? AssumeThreadIdsInRangeInDimension : Expr.And(AssumeThreadIdsInRange, AssumeThreadIdsInRangeInDimension);
- }
+ AssumeThreadIdsInRange = (null == AssumeThreadIdsInRange) ? AssumeThreadIdsInRangeInDimension : Expr.And(AssumeThreadIdsInRange, AssumeThreadIdsInRangeInDimension);
}
private Expr MakeBitVectorBinaryBoolean(string functionName, Expr lhs, Expr rhs)
@@ -1888,6 +2071,9 @@ namespace GPUVerify
bool HalfDualise = HalfDualisedProcedureNames.Contains(proc.Name);
+ proc.Requires = DualiseRequires(proc.Requires);
+ proc.Ensures = DualiseEnsures(proc.Ensures);
+
proc.InParams = DualiseVariableSequence(proc.InParams, HalfDualise);
proc.OutParams = DualiseVariableSequence(proc.OutParams, HalfDualise);
IdentifierExprSeq NewModifies = new IdentifierExprSeq();
@@ -1952,6 +2138,42 @@ namespace GPUVerify
}
+ private EnsuresSeq DualiseEnsures(EnsuresSeq ensuresSeq)
+ {
+ EnsuresSeq newEnsures = new EnsuresSeq();
+ foreach (Ensures e in ensuresSeq)
+ {
+ newEnsures.Add(new Ensures(e.Free, new VariableDualiser(1).VisitExpr(e.Condition.Clone() as Expr)));
+ if (!CommandLineOptions.Symmetry || !ContainsAsymmetricExpression(e.Condition))
+ {
+ newEnsures.Add(new Ensures(e.Free, new VariableDualiser(2).VisitExpr(e.Condition.Clone() as Expr)));
+ }
+ }
+ return newEnsures;
+ }
+
+ private RequiresSeq DualiseRequires(RequiresSeq requiresSeq)
+ {
+ RequiresSeq newRequires = new RequiresSeq();
+ foreach (Requires r in requiresSeq)
+ {
+ newRequires.Add(new Requires(r.Free, new VariableDualiser(1).VisitExpr(r.Condition.Clone() as Expr)));
+
+ if (!CommandLineOptions.Symmetry || !ContainsAsymmetricExpression(r.Condition))
+ {
+ newRequires.Add(new Requires(r.Free, new VariableDualiser(2).VisitExpr(r.Condition.Clone() as Expr)));
+ }
+ }
+ return newRequires;
+ }
+
+ private bool ContainsAsymmetricExpression(Expr expr)
+ {
+ AsymmetricExpressionFinder finder = new AsymmetricExpressionFinder();
+ finder.VisitExpr(expr);
+ return finder.foundAsymmetricExpr();
+ }
+
private static VariableSeq DualiseVariableSequence(VariableSeq seq, bool HalfDualise)
{
VariableSeq result = new VariableSeq();
@@ -1981,12 +2203,29 @@ namespace GPUVerify
// Add predicate to start of parameter list
Procedure proc = d as Procedure;
VariableSeq NewIns = new VariableSeq();
- NewIns.Add(new LocalVariable(proc.tok, new TypedIdent(proc.tok, "_P", Microsoft.Boogie.Type.Bool)));
+ TypedIdent enabled = new TypedIdent(proc.tok, "_P", Microsoft.Boogie.Type.Bool);
+ NewIns.Add(new LocalVariable(proc.tok, enabled));
foreach (Variable v in proc.InParams)
{
NewIns.Add(v);
}
proc.InParams = NewIns;
+
+ RequiresSeq newRequires = new RequiresSeq();
+ foreach (Requires r in proc.Requires)
+ {
+ newRequires.Add(new Requires(r.Free, Predicator.ProcessEnabledIntrinsics(r.Condition, enabled)));
+ }
+ proc.Requires = newRequires;
+
+ EnsuresSeq newEnsures = new EnsuresSeq();
+ foreach (Ensures e in proc.Ensures)
+ {
+ newEnsures.Add(new Ensures(e.Free, Predicator.ProcessEnabledIntrinsics(e.Condition, enabled)));
+ }
+ proc.Ensures = newEnsures;
+
+
}
}
@@ -2109,7 +2348,7 @@ namespace GPUVerify
else if (c is AssertCmd)
{
AssertCmd ass = c as AssertCmd;
- if (HalfDualise)
+ if (HalfDualise || ContainsAsymmetricExpression(ass.Expr))
{
result.simpleCmds.Add(new AssertCmd(c.tok, new VariableDualiser(1).VisitExpr(ass.Expr.Clone() as Expr)));
}
@@ -2121,7 +2360,7 @@ namespace GPUVerify
else if (c is AssumeCmd)
{
AssumeCmd ass = c as AssumeCmd;
- if (HalfDualise)
+ if (HalfDualise || ContainsAsymmetricExpression(ass.Expr))
{
result.simpleCmds.Add(new AssumeCmd(c.tok, new VariableDualiser(1).VisitExpr(ass.Expr.Clone() as Expr)));
}
@@ -2138,7 +2377,11 @@ namespace GPUVerify
if (bb.ec is WhileCmd)
{
- result.ec = new WhileCmd(bb.ec.tok, Expr.Or(new VariableDualiser(1).VisitExpr((bb.ec as WhileCmd).Guard), new VariableDualiser(2).VisitExpr((bb.ec as WhileCmd).Guard)), (bb.ec as WhileCmd).Invariants, MakeDual((bb.ec as WhileCmd).Body, HalfDualise));
+ result.ec = new WhileCmd(bb.ec.tok,
+ Expr.Or(new VariableDualiser(1).VisitExpr((bb.ec as WhileCmd).Guard),
+ new VariableDualiser(2).VisitExpr((bb.ec as WhileCmd).Guard)
+ ),
+ MakeDualInvariants((bb.ec as WhileCmd).Invariants), MakeDual((bb.ec as WhileCmd).Body, HalfDualise));
}
else
{
@@ -2149,6 +2392,21 @@ namespace GPUVerify
}
+ private List<PredicateCmd> MakeDualInvariants(List<PredicateCmd> originalInvariants)
+ {
+ List<PredicateCmd> result = new List<PredicateCmd>();
+ foreach(PredicateCmd p in originalInvariants)
+ {
+ result.Add(new AssertCmd(p.tok, new VariableDualiser(1).VisitExpr(p.Expr.Clone() as Expr)));
+ if (!CommandLineOptions.Symmetry || !ContainsAsymmetricExpression(p.Expr))
+ {
+ result.Add(new AssertCmd(p.tok, new VariableDualiser(2).VisitExpr(p.Expr.Clone() as Expr)));
+ }
+ }
+
+ return result;
+ }
+
private void MakeDualLocalVariables(Implementation impl, bool HalfDualise)
{
VariableSeq NewLocalVars = new VariableSeq();
@@ -2204,101 +2462,90 @@ namespace GPUVerify
if (!KernelHasIdX())
{
- MissingKernelAttributeError("Kernel", LOCAL_ID_X_STRING);
+ MissingKernelAttributeError(LOCAL_ID_X_STRING);
}
if (!KernelHasGroupSizeX())
{
- MissingKernelAttributeError("Kernel", GROUP_SIZE_X_STRING);
+ MissingKernelAttributeError(GROUP_SIZE_X_STRING);
}
if (!KernelHasNumGroupsX())
{
- MissingKernelAttributeError("Kernel", NUM_GROUPS_X_STRING);
+ MissingKernelAttributeError(NUM_GROUPS_X_STRING);
}
if (!KernelHasGroupIdX())
{
- MissingKernelAttributeError("Kernel", GROUP_ID_X_STRING);
+ MissingKernelAttributeError(GROUP_ID_X_STRING);
}
- if (KernelHasIdY() || KernelHasGroupSizeY() || KernelHasNumGroupsY() || KernelHasGroupIdY())
+ if (!KernelHasIdY())
{
-
- if (!KernelHasIdY())
- {
- MissingKernelAttributeError("2D kernel", LOCAL_ID_Y_STRING);
- }
-
- if (!KernelHasGroupSizeY())
- {
- MissingKernelAttributeError("2D kernel", GROUP_SIZE_Y_STRING);
- }
-
- if (!KernelHasNumGroupsY())
- {
- MissingKernelAttributeError("2D kernel", NUM_GROUPS_Y_STRING);
- }
-
- if (!KernelHasGroupIdY())
- {
- MissingKernelAttributeError("2D kernel", GROUP_ID_Y_STRING);
- }
-
+ MissingKernelAttributeError(LOCAL_ID_Y_STRING);
}
- if (KernelHasIdZ() || KernelHasGroupSizeZ() || KernelHasNumGroupsZ() || KernelHasGroupIdZ())
+ if (!KernelHasGroupSizeY())
{
+ MissingKernelAttributeError(GROUP_SIZE_Y_STRING);
+ }
- if (!KernelHasIdY())
- {
- MissingKernelAttributeError("3D kernel", LOCAL_ID_Y_STRING);
- }
+ if (!KernelHasNumGroupsY())
+ {
+ MissingKernelAttributeError(NUM_GROUPS_Y_STRING);
+ }
- if (!KernelHasGroupSizeY())
- {
- MissingKernelAttributeError("3D kernel", GROUP_SIZE_Y_STRING);
- }
+ if (!KernelHasGroupIdY())
+ {
+ MissingKernelAttributeError(GROUP_ID_Y_STRING);
+ }
- if (!KernelHasNumGroupsY())
- {
- MissingKernelAttributeError("3D kernel", NUM_GROUPS_Y_STRING);
- }
+ if (!KernelHasIdY())
+ {
+ MissingKernelAttributeError(LOCAL_ID_Y_STRING);
+ }
- if (!KernelHasGroupIdY())
- {
- MissingKernelAttributeError("3D kernel", GROUP_ID_Y_STRING);
- }
+ if (!KernelHasGroupSizeY())
+ {
+ MissingKernelAttributeError(GROUP_SIZE_Y_STRING);
+ }
- if (!KernelHasIdZ())
- {
- MissingKernelAttributeError("3D kernel", LOCAL_ID_Z_STRING);
- }
+ if (!KernelHasNumGroupsY())
+ {
+ MissingKernelAttributeError(NUM_GROUPS_Y_STRING);
+ }
- if (!KernelHasGroupSizeZ())
- {
- MissingKernelAttributeError("3D kernel", GROUP_SIZE_Z_STRING);
- }
+ if (!KernelHasGroupIdY())
+ {
+ MissingKernelAttributeError(GROUP_ID_Y_STRING);
+ }
- if (!KernelHasNumGroupsZ())
- {
- MissingKernelAttributeError("3D kernel", NUM_GROUPS_Z_STRING);
- }
+ if (!KernelHasIdZ())
+ {
+ MissingKernelAttributeError(LOCAL_ID_Z_STRING);
+ }
- if (!KernelHasGroupIdZ())
- {
- MissingKernelAttributeError("3D kernel", GROUP_ID_Z_STRING);
- }
+ if (!KernelHasGroupSizeZ())
+ {
+ MissingKernelAttributeError(GROUP_SIZE_Z_STRING);
+ }
+ if (!KernelHasNumGroupsZ())
+ {
+ MissingKernelAttributeError(NUM_GROUPS_Z_STRING);
+ }
+ if (!KernelHasGroupIdZ())
+ {
+ MissingKernelAttributeError(GROUP_ID_Z_STRING);
}
return ErrorCount;
}
- private void MissingKernelAttributeError(string kindOfKernel, string attribute)
+ private void MissingKernelAttributeError(string attribute)
{
- Error(KernelProcedure.tok, kindOfKernel + " must declare global constant marked with attribute ':" + attribute + "'");
+ Error(KernelProcedure.tok, "Kernel must declare global constant marked with attribute ':" + attribute + "'");
}
public static bool IsThreadLocalIdConstant(Variable variable)
diff --git a/Source/GPUVerify/GPUVerify.csproj b/Source/GPUVerify/GPUVerify.csproj
index 6956b973..66be025a 100644
--- a/Source/GPUVerify/GPUVerify.csproj
+++ b/Source/GPUVerify/GPUVerify.csproj
@@ -104,7 +104,12 @@
</ItemGroup>
<ItemGroup>
<Compile Include="AccessCollector.cs" />
+ <Compile Include="AccessInvariantProcessor.cs" />
<Compile Include="AccessRecord.cs" />
+ <Compile Include="AsymmetricExpressionFinder.cs" />
+ <Compile Include="StructuredProgramVisitor.cs" />
+ <Compile Include="CrossThreadInvariantProcessor.cs" />
+ <Compile Include="EnabledToPredicateVisitor.cs" />
<Compile Include="CommandLineOptions.cs" />
<Compile Include="ElementEncodingraceInstrumenter.cs" />
<Compile Include="GPUVerifier.cs" />
diff --git a/Source/GPUVerify/IRaceInstrumenter.cs b/Source/GPUVerify/IRaceInstrumenter.cs
index 9a1c0d8c..2c9d2410 100644
--- a/Source/GPUVerify/IRaceInstrumenter.cs
+++ b/Source/GPUVerify/IRaceInstrumenter.cs
@@ -20,10 +20,14 @@ namespace GPUVerify
BigBlock MakeRaceCheckingStatements(IToken tok);
- void CheckForRaces(IToken tok, BigBlock bb, Variable v, bool ReadWriteOnly);
+ void CheckForRaces(BigBlock bb, Variable v, bool ReadWriteOnly);
void AddRaceCheckingCandidateRequires(Procedure Proc);
void AddRaceCheckingCandidateEnsures(Procedure Proc);
+
+ void AddNoRaceContract(Procedure Proc);
+
+ void AddNoRaceInvariants(Implementation Impl);
}
}
diff --git a/Source/GPUVerify/NullRaceInstrumenter.cs b/Source/GPUVerify/NullRaceInstrumenter.cs
index a825a2eb..3a8f8356 100644
--- a/Source/GPUVerify/NullRaceInstrumenter.cs
+++ b/Source/GPUVerify/NullRaceInstrumenter.cs
@@ -19,7 +19,7 @@ namespace GPUVerify
}
- public void CheckForRaces(IToken tok, BigBlock bb, Variable v, bool ReadWriteOnly)
+ public void CheckForRaces(BigBlock bb, Variable v, bool ReadWriteOnly)
{
}
@@ -42,6 +42,17 @@ namespace GPUVerify
{
}
-
+
+
+ public void AddNoRaceContract(Procedure proc)
+ {
+
+ }
+
+ public void AddNoRaceInvariants(Implementation impl)
+ {
+
+ }
+
}
}
diff --git a/Source/GPUVerify/Predicator.cs b/Source/GPUVerify/Predicator.cs
index e2af8185..a2059b56 100644
--- a/Source/GPUVerify/Predicator.cs
+++ b/Source/GPUVerify/Predicator.cs
@@ -7,19 +7,24 @@ using Microsoft.Boogie;
namespace GPUVerify
{
- class Predicator
+ class Predicator : StructuredProgramVisitor
{
private bool AddPredicateParameter;
private int WhileLoopCounter;
private int IfCounter;
private static HashSet<Microsoft.Boogie.Type> RequiredHavocVariables;
+ private Stack<Expr> predicate;
+ private Stack<IdentifierExpr> enclosingLoopPredicate;
+
internal Predicator(bool AddPredicateParameter)
{
this.AddPredicateParameter = AddPredicateParameter;
WhileLoopCounter = 0;
IfCounter = 0;
RequiredHavocVariables = new HashSet<Microsoft.Boogie.Type>();
+ predicate = new Stack<Expr>();
+ enclosingLoopPredicate = new Stack<IdentifierExpr>();
}
internal void transform(Implementation impl)
@@ -43,205 +48,238 @@ namespace GPUVerify
Predicate = Expr.True;
}
- impl.StructuredStmts = MakePredicated(impl.StructuredStmts, Predicate, null);
+ predicate.Push(Predicate);
+ enclosingLoopPredicate.Push(null);
+
+ impl.StructuredStmts = VisitStmtList(impl.StructuredStmts);
+
AddPredicateLocalVariables(impl);
}
+ public override CmdSeq VisitCmd(Cmd c)
+ {
+ if (c is CallCmd || !predicate.Peek().Equals(Expr.True))
+ {
+ return base.VisitCmd(c);
+ }
+
+ return new CmdSeq(new Cmd[] { c });
- private StmtList MakePredicated(StmtList sl, Expr predicate, IdentifierExpr EnclosingLoopPredicate)
+ }
+
+ public override CmdSeq VisitCallCmd(CallCmd Call)
{
- StmtList result = new StmtList(new List<BigBlock>(), sl.EndCurly);
+ List<Expr> NewIns = new List<Expr>();
+ NewIns.Add(predicate.Peek());
- foreach (BigBlock bodyBlock in sl.BigBlocks)
+ foreach (Expr e in Call.Ins)
{
- List<BigBlock> newBigBlocks = MakePredicated(bodyBlock, predicate, EnclosingLoopPredicate);
- foreach (BigBlock newBigBlock in newBigBlocks)
- {
- result.BigBlocks.Add(newBigBlock);
- }
+ NewIns.Add(e);
}
- return result;
+ return new CmdSeq(
+ new Cmd[] { new CallCmd(Call.tok, Call.callee, NewIns, Call.Outs) });
}
- private List<BigBlock> MakePredicated(BigBlock b, Expr IncomingPredicate, IdentifierExpr EnclosingLoopPredicate)
+ public override CmdSeq VisitAssignCmd(AssignCmd assign)
{
- // Not sure what to do about the transfer command
+ Debug.Assert(assign.Lhss.Count == 1 && assign.Rhss.Count == 1);
- List<BigBlock> result = new List<BigBlock>();
+ ExprSeq iteArgs = new ExprSeq();
+ iteArgs.Add(predicate.Peek());
+ iteArgs.Add(assign.Rhss.ElementAt(0));
+ iteArgs.Add(assign.Lhss.ElementAt(0).AsExpr);
+ NAryExpr ite = new NAryExpr(assign.tok, new IfThenElse(assign.tok), iteArgs);
- BigBlock firstBigBlock = new BigBlock(b.tok, b.LabelName, new CmdSeq(), null, b.tc);
- result.Add(firstBigBlock);
+ List<Expr> newRhs = new List<Expr>();
+ newRhs.Add(ite);
- foreach (Cmd c in b.simpleCmds)
- {
- if (c is CallCmd)
- {
+ return new CmdSeq(new Cmd[] { new AssignCmd(assign.tok, assign.Lhss, newRhs) });
- CallCmd Call = c as CallCmd;
+ }
- List<Expr> NewIns = new List<Expr>();
- NewIns.Add(IncomingPredicate);
+ public override CmdSeq VisitHavocCmd(HavocCmd havoc)
+ {
+ CmdSeq result = new CmdSeq();
- foreach (Expr e in Call.Ins)
- {
- NewIns.Add(e);
- }
+ Debug.Assert(havoc.Vars.Length == 1);
- CallCmd NewCallCmd = new CallCmd(Call.tok, Call.callee, NewIns, Call.Outs);
+ Microsoft.Boogie.Type type = havoc.Vars[0].Decl.TypedIdent.Type;
+ Debug.Assert(type != null);
- firstBigBlock.simpleCmds.Add(NewCallCmd);
- }
- else if (IncomingPredicate.Equals(Expr.True))
- {
- firstBigBlock.simpleCmds.Add(c);
- }
- else if (c is AssignCmd)
- {
- AssignCmd assign = c as AssignCmd;
- Debug.Assert(assign.Lhss.Count == 1 && assign.Rhss.Count == 1);
+ RequiredHavocVariables.Add(type);
- ExprSeq iteArgs = new ExprSeq();
- iteArgs.Add(IncomingPredicate);
- iteArgs.Add(assign.Rhss.ElementAt(0));
- iteArgs.Add(assign.Lhss.ElementAt(0).AsExpr);
- NAryExpr ite = new NAryExpr(assign.tok, new IfThenElse(assign.tok), iteArgs);
+ IdentifierExpr HavocTempExpr = new IdentifierExpr(havoc.tok, new LocalVariable(havoc.tok, new TypedIdent(havoc.tok, "_HAVOC_" + type.ToString(), type)));
+ result.Add(new HavocCmd(havoc.tok, new IdentifierExprSeq(new IdentifierExpr[] {
+ HavocTempExpr
+ })));
- List<Expr> newRhs = new List<Expr>();
- newRhs.Add(ite);
+ List<AssignLhs> lhss = new List<AssignLhs>();
+ lhss.Add(new SimpleAssignLhs(havoc.tok, havoc.Vars[0]));
- AssignCmd newAssign = new AssignCmd(assign.tok, assign.Lhss, newRhs);
+ List<Expr> rhss = new List<Expr>();
+ rhss.Add(new NAryExpr(havoc.tok, new IfThenElse(havoc.tok), new ExprSeq(
+ new Expr[] { predicate.Peek(), HavocTempExpr, havoc.Vars[0] })));
- firstBigBlock.simpleCmds.Add(newAssign);
- }
- else if (c is HavocCmd)
- {
- HavocCmd havoc = c as HavocCmd;
- Debug.Assert(havoc.Vars.Length == 1);
+ result.Add(new AssignCmd(havoc.tok, lhss, rhss));
- Microsoft.Boogie.Type type = havoc.Vars[0].Decl.TypedIdent.Type;
- Debug.Assert(type != null);
+ return result;
- RequiredHavocVariables.Add(type);
+ }
- IdentifierExpr HavocTempExpr = new IdentifierExpr(havoc.tok, new LocalVariable(havoc.tok, new TypedIdent(havoc.tok, "_HAVOC_" + type.ToString(), type)));
- firstBigBlock.simpleCmds.Add(new HavocCmd(havoc.tok, new IdentifierExprSeq(new IdentifierExpr[] {
- HavocTempExpr
- })));
+ public override CmdSeq VisitAssertCmd(AssertCmd assert)
+ {
+ return new CmdSeq(new Cmd[] {
+ new AssertCmd(assert.tok, Expr.Imp(predicate.Peek(), assert.Expr))
+ });
+ }
- List<AssignLhs> lhss = new List<AssignLhs>();
- lhss.Add(new SimpleAssignLhs(havoc.tok, havoc.Vars[0]));
+ public override CmdSeq VisitAssumeCmd(AssumeCmd assume)
+ {
+ return new CmdSeq(new Cmd[] {
+ new AssumeCmd(assume.tok, Expr.Imp(predicate.Peek(), assume.Expr))
+ });
+ }
- List<Expr> rhss = new List<Expr>();
- rhss.Add(new NAryExpr(havoc.tok, new IfThenElse(havoc.tok), new ExprSeq(new Expr[] { IncomingPredicate, HavocTempExpr, havoc.Vars[0] })));
+ public override List<BigBlock> VisitBigBlock(BigBlock bb)
+ {
+ BigBlock firstBigBlock = new BigBlock(bb.tok, bb.LabelName, new CmdSeq(), null, bb.tc);
- firstBigBlock.simpleCmds.Add(new AssignCmd(havoc.tok, lhss, rhss));
+ List<BigBlock> result = new List<BigBlock>();
+ result.Add(firstBigBlock);
- }
- else if (c is AssertCmd)
- {
- firstBigBlock.simpleCmds.Add(new AssertCmd(c.tok, Expr.Imp(IncomingPredicate, (c as AssertCmd).Expr)));
- }
- else if (c is AssumeCmd)
- {
- firstBigBlock.simpleCmds.Add(new AssumeCmd(c.tok, Expr.Imp(IncomingPredicate, (c as AssumeCmd).Expr)));
- }
- else
- {
- Debug.Assert(false);
- }
- }
+ firstBigBlock.simpleCmds = VisitCmdSeq(bb.simpleCmds);
- if (b.ec is WhileCmd)
+ if (bb.ec is WhileCmd)
{
+ WhileCmd whileCmd = bb.ec as WhileCmd;
+
string LoopPredicate = "_LC" + WhileLoopCounter;
WhileLoopCounter++;
- IdentifierExpr PredicateExpr = new IdentifierExpr(b.ec.tok, new LocalVariable(b.ec.tok, new TypedIdent(b.ec.tok, LoopPredicate, Microsoft.Boogie.Type.Bool)));
- Expr GuardExpr = (b.ec as WhileCmd).Guard;
+ TypedIdent LoopPredicateTypedIdent = new TypedIdent(whileCmd.tok, LoopPredicate, Microsoft.Boogie.Type.Bool);
+
+ IdentifierExpr PredicateExpr = new IdentifierExpr(whileCmd.tok, new LocalVariable(whileCmd.tok, LoopPredicateTypedIdent));
+ Expr GuardExpr = whileCmd.Guard;
List<AssignLhs> WhilePredicateLhss = new List<AssignLhs>();
- WhilePredicateLhss.Add(new SimpleAssignLhs(b.ec.tok, PredicateExpr));
+ WhilePredicateLhss.Add(new SimpleAssignLhs(whileCmd.tok, PredicateExpr));
List<Expr> WhilePredicateRhss = new List<Expr>();
- WhilePredicateRhss.Add(IncomingPredicate.Equals(Expr.True) ? GuardExpr : Expr.And(IncomingPredicate, GuardExpr));
+ WhilePredicateRhss.Add(predicate.Peek().Equals(Expr.True) ? GuardExpr : Expr.And(predicate.Peek(), GuardExpr));
- firstBigBlock.simpleCmds.Add(new AssignCmd(b.ec.tok, WhilePredicateLhss, WhilePredicateRhss));
+ firstBigBlock.simpleCmds.Add(new AssignCmd(whileCmd.tok, WhilePredicateLhss, WhilePredicateRhss));
- WhileCmd NewWhile = new WhileCmd(b.ec.tok, PredicateExpr, (b.ec as WhileCmd).Invariants, MakePredicated((b.ec as WhileCmd).Body, PredicateExpr, PredicateExpr));
+ predicate.Push(PredicateExpr);
+ enclosingLoopPredicate.Push(PredicateExpr);
+ WhileCmd NewWhile = new WhileCmd(whileCmd.tok, PredicateExpr,
+ VisitWhileInvariants(whileCmd.Invariants),
+ VisitStmtList(whileCmd.Body));
+ enclosingLoopPredicate.Pop();
+ predicate.Pop();
List<Expr> UpdatePredicateRhss = new List<Expr>();
UpdatePredicateRhss.Add(Expr.And(PredicateExpr, GuardExpr));
CmdSeq updateCmd = new CmdSeq();
- updateCmd.Add(new AssignCmd(b.ec.tok, WhilePredicateLhss, UpdatePredicateRhss));
+ updateCmd.Add(new AssignCmd(whileCmd.tok, WhilePredicateLhss, UpdatePredicateRhss));
- NewWhile.Body.BigBlocks.Add(new BigBlock(b.ec.tok, "update_" + LoopPredicate, updateCmd, null, null));
+ NewWhile.Body.BigBlocks.Add(new BigBlock(whileCmd.tok, "update_" + LoopPredicate, updateCmd, null, null));
firstBigBlock.ec = NewWhile;
}
- else if (b.ec is IfCmd)
+ else if (bb.ec is IfCmd)
{
- IfCmd IfCommand = b.ec as IfCmd;
+ IfCmd IfCommand = bb.ec as IfCmd;
string IfPredicate = "_P" + IfCounter;
IfCounter++;
- IdentifierExpr PredicateExpr = new IdentifierExpr(b.ec.tok, new LocalVariable(b.ec.tok, new TypedIdent(b.ec.tok, IfPredicate, Microsoft.Boogie.Type.Bool)));
+ IdentifierExpr PredicateExpr = new IdentifierExpr(IfCommand.tok,
+ new LocalVariable(IfCommand.tok, new TypedIdent(IfCommand.tok, IfPredicate, Microsoft.Boogie.Type.Bool)));
Expr GuardExpr = IfCommand.Guard;
List<AssignLhs> IfPredicateLhss = new List<AssignLhs>();
- IfPredicateLhss.Add(new SimpleAssignLhs(b.ec.tok, PredicateExpr));
+ IfPredicateLhss.Add(new SimpleAssignLhs(IfCommand.tok, PredicateExpr));
List<Expr> IfPredicateRhss = new List<Expr>();
IfPredicateRhss.Add(GuardExpr);
- firstBigBlock.simpleCmds.Add(new AssignCmd(b.ec.tok, IfPredicateLhss, IfPredicateRhss));
+ firstBigBlock.simpleCmds.Add(new AssignCmd(IfCommand.tok, IfPredicateLhss, IfPredicateRhss));
Debug.Assert(IfCommand.elseIf == null); // We need to preprocess these away
- StmtList PredicatedThen = MakePredicated(IfCommand.thn, Expr.And(IncomingPredicate, PredicateExpr), EnclosingLoopPredicate);
+ predicate.Push(Expr.And(predicate.Peek(), PredicateExpr));
+ StmtList PredicatedThen = VisitStmtList(IfCommand.thn);
+ predicate.Pop();
+ result.AddRange(PredicatedThen.BigBlocks);
- foreach (BigBlock bb in PredicatedThen.BigBlocks)
+ if(IfCommand.elseIf != null)
{
- result.Add(bb);
+ throw new InvalidOperationException();
}
if (IfCommand.elseBlock != null)
{
- StmtList PredicatedElse = MakePredicated(IfCommand.elseBlock, Expr.And(IncomingPredicate, Expr.Not(PredicateExpr)), EnclosingLoopPredicate);
-
- foreach (BigBlock bb in PredicatedElse.BigBlocks)
- {
- result.Add(bb);
- }
+ predicate.Push(Expr.And(predicate.Peek(), Expr.Not(PredicateExpr)));
+ StmtList PredicatedElse = VisitStmtList(IfCommand.elseBlock);
+ predicate.Pop();
+ result.AddRange(PredicatedElse.BigBlocks);
}
+ }
+ else if (bb.ec is BreakCmd)
+ {
+ firstBigBlock.simpleCmds.Add(new AssignCmd(bb.tok,
+ new List<AssignLhs>(new AssignLhs[] { new SimpleAssignLhs(bb.tok, enclosingLoopPredicate.Peek()) }),
+ new List<Expr>(new Expr[] { new NAryExpr(bb.tok, new IfThenElse(bb.tok), new ExprSeq(
+ new Expr[] { predicate.Peek(), Expr.False, enclosingLoopPredicate.Peek() })) })
+ ));
+ firstBigBlock.ec = null;
+ }
+ else if (bb.ec != null)
+ {
+ throw new InvalidOperationException();
+ }
+ return result;
+ }
- }
- else if (b.ec is BreakCmd)
- {
+ public override IfCmd VisitIfCmd(IfCmd ifCmd)
+ {
+ throw new InvalidOperationException();
+ }
+ public override WhileCmd VisitWhileCmd(WhileCmd whileCmd)
+ {
+ throw new InvalidOperationException();
+ }
- firstBigBlock.simpleCmds.Add(new AssignCmd(b.tok,
- new List<AssignLhs>(new AssignLhs[] { new SimpleAssignLhs(b.tok, EnclosingLoopPredicate) }),
- new List<Expr>(new Expr[] { new NAryExpr(b.tok, new IfThenElse(b.tok), new ExprSeq(new Expr[] { IncomingPredicate, Expr.False, EnclosingLoopPredicate })) })
- ));
- firstBigBlock.ec = null;
+ public override BreakCmd VisitBreakCmd(BreakCmd breakCmd)
+ {
+ throw new InvalidOperationException();
+ }
- }
- else
+ public override List<PredicateCmd> VisitWhileInvariants(List<PredicateCmd> invariants)
+ {
+ List<PredicateCmd> result = new List<PredicateCmd>();
+
+ foreach (PredicateCmd cmd in invariants)
{
- Debug.Assert(b.ec == null);
+ result.Add(new AssertCmd(cmd.tok, ProcessEnabledIntrinsics(cmd.Expr, enclosingLoopPredicate.Peek().Decl.TypedIdent)));
}
return result;
}
+ internal static Expr ProcessEnabledIntrinsics(Expr expr, TypedIdent currentPredicate)
+ {
+ return new EnabledToPredicateVisitor(currentPredicate).VisitExpr(expr);
+ }
+
private void AddPredicateLocalVariables(Implementation impl)
{
diff --git a/Source/GPUVerify/RaceInstrumenterBase.cs b/Source/GPUVerify/RaceInstrumenterBase.cs
index 692f1288..5909ec07 100644
--- a/Source/GPUVerify/RaceInstrumenterBase.cs
+++ b/Source/GPUVerify/RaceInstrumenterBase.cs
@@ -353,7 +353,7 @@ namespace GPUVerify
{
foreach (Variable v in NonLocalStateToCheck.getAllNonLocalVariables())
{
- CheckForRaces(tok, checkForRaces, v, false);
+ CheckForRaces(checkForRaces, v, false);
}
}
@@ -372,7 +372,7 @@ namespace GPUVerify
protected abstract void SetNoAccessOccurred(IToken tok, BigBlock bb, Variable v, string AccessType);
- public abstract void CheckForRaces(IToken tok, BigBlock bb, Variable v, bool ReadWriteOnly);
+ public abstract void CheckForRaces(BigBlock bb, Variable v, bool ReadWriteOnly);
protected void MakeLogAccessProcedureHeader(Variable v, string ReadOrWrite, out Variable XParameterVariable, out Variable YParameterVariable, out Variable ZParameterVariable, out Procedure LogReadOrWriteProcedure)
{
@@ -462,6 +462,74 @@ namespace GPUVerify
protected abstract Expr NoReadOrWriteExpr(Variable v, string ReadOrWrite, string OneOrTwo);
+ public void AddNoRaceContract(Procedure proc)
+ {
+ foreach (Variable v in NonLocalStateToCheck.getAllNonLocalVariables())
+ {
+ proc.Requires.Add(new Requires(false, Expr.Not(GenerateRaceCondition(v, "WRITE", "WRITE"))));
+ proc.Requires.Add(new Requires(false, Expr.Not(GenerateRaceCondition(v, "READ", "WRITE"))));
+ if (!CommandLineOptions.Symmetry)
+ {
+ proc.Requires.Add(new Requires(false, Expr.Not(GenerateRaceCondition(v, "WRITE", "READ"))));
+ }
+
+ proc.Ensures.Add(new Ensures(false, Expr.Not(GenerateRaceCondition(v, "WRITE", "WRITE"))));
+ proc.Ensures.Add(new Ensures(false, Expr.Not(GenerateRaceCondition(v, "READ", "WRITE"))));
+ if (!CommandLineOptions.Symmetry)
+ {
+ proc.Ensures.Add(new Ensures(false, Expr.Not(GenerateRaceCondition(v, "WRITE", "READ"))));
+ }
+
+ }
+ }
+
+ public void AddNoRaceInvariants(Implementation impl)
+ {
+ AddNoRaceInvariants(impl.StructuredStmts);
+ }
+
+ private void AddNoRaceInvariants(StmtList stmtList)
+ {
+ foreach (BigBlock bb in stmtList.BigBlocks)
+ {
+ AddNoRaceInvariants(bb);
+ }
+ }
+
+ private void AddNoRaceInvariants(BigBlock bb)
+ {
+ if (bb.ec is WhileCmd)
+ {
+ WhileCmd wc = bb.ec as WhileCmd;
+ foreach (Variable v in NonLocalStateToCheck.getAllNonLocalVariables())
+ {
+ wc.Invariants.Add(new AssertCmd(v.tok, Expr.Not(GenerateRaceCondition(v, "WRITE", "WRITE"))));
+ wc.Invariants.Add(new AssertCmd(v.tok, Expr.Not(GenerateRaceCondition(v, "READ", "WRITE"))));
+ if (!CommandLineOptions.Symmetry)
+ {
+ wc.Invariants.Add(new AssertCmd(v.tok, Expr.Not(GenerateRaceCondition(v, "WRITE", "READ"))));
+ }
+ }
+
+ AddNoRaceInvariants(wc.Body);
+
+ }
+ else if (bb.ec is IfCmd)
+ {
+ AddNoRaceInvariants((bb.ec as IfCmd).thn);
+ if ((bb.ec as IfCmd).elseBlock != null)
+ {
+ AddNoRaceInvariants((bb.ec as IfCmd).elseBlock);
+ }
+ }
+ else
+ {
+ Debug.Assert(bb.ec == null);
+ }
+ }
+
+
+ protected abstract Expr GenerateRaceCondition(Variable v, string FirstAccessType, string SecondAccessType);
}
}
diff --git a/Source/GPUVerify/SetEncodingRaceInstrumenter.cs b/Source/GPUVerify/SetEncodingRaceInstrumenter.cs
index e7e5854e..d9f674da 100644
--- a/Source/GPUVerify/SetEncodingRaceInstrumenter.cs
+++ b/Source/GPUVerify/SetEncodingRaceInstrumenter.cs
@@ -206,7 +206,7 @@ namespace GPUVerify
}
- public override void CheckForRaces(IToken tok, BigBlock bb, Variable v, bool ReadWriteOnly)
+ public override void CheckForRaces(BigBlock bb, Variable v, bool ReadWriteOnly)
{
if (!ReadWriteOnly)
{
@@ -257,14 +257,21 @@ namespace GPUVerify
return mt3.Arguments[0];
}
- private static void AddRaceCheck(BigBlock bb, Variable v, String Access1, String Access2)
+ private void AddRaceCheck(BigBlock bb, Variable v, String Access1, String Access2)
+ {
+ Expr AssertExpr = GenerateRaceCondition(v, Access1, Access2);
+
+ bb.simpleCmds.Add(new AssertCmd(v.tok, AssertExpr));
+ }
+
+ protected override Expr GenerateRaceCondition(Variable v, String Access1, String Access2)
{
VariableSeq DummyVars1;
Expr SetExpr1 = AccessExpr(v, Access1, 1, out DummyVars1);
VariableSeq DummyVars2;
Expr SetExpr2 = AccessExpr(v, Access2, 2, out DummyVars2);
-
+
Debug.Assert(DummyVars1.Length == DummyVars2.Length);
for (int i = 0; i < DummyVars1.Length; i++)
{
@@ -294,8 +301,7 @@ namespace GPUVerify
{
AssertExpr = new ForallExpr(v.tok, DummyVars1, AssertExpr);
}
-
- bb.simpleCmds.Add(new AssertCmd(v.tok, AssertExpr));
+ return AssertExpr;
}
private static void SetNameDeep(IdentifierExpr e, string name)
diff --git a/Source/GPUVerify/StructuredProgramVisitor.cs b/Source/GPUVerify/StructuredProgramVisitor.cs
new file mode 100644
index 00000000..4b2d1c47
--- /dev/null
+++ b/Source/GPUVerify/StructuredProgramVisitor.cs
@@ -0,0 +1,152 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Microsoft.Boogie;
+
+namespace GPUVerify
+{
+ class StructuredProgramVisitor
+ {
+
+ public virtual StmtList VisitStmtList(StmtList stmtList)
+ {
+ StmtList result = new StmtList(new List<BigBlock>(), stmtList.EndCurly);
+
+ foreach (BigBlock bb in stmtList.BigBlocks)
+ {
+ result.BigBlocks.AddRange(VisitBigBlock(bb));
+ }
+
+ return result;
+
+ }
+
+ public virtual List<BigBlock> VisitBigBlock(BigBlock bb)
+ {
+ BigBlock firstBigBlock = new BigBlock(bb.tok, bb.LabelName, new CmdSeq(), null, bb.tc);
+
+ firstBigBlock.simpleCmds = VisitCmdSeq(bb.simpleCmds);
+
+ if (bb.ec is WhileCmd)
+ {
+ firstBigBlock.ec = VisitWhileCmd(bb.ec as WhileCmd);
+ }
+ else if (bb.ec is IfCmd)
+ {
+ firstBigBlock.ec = VisitIfCmd(bb.ec as IfCmd);
+ }
+ else if (bb.ec is BreakCmd)
+ {
+ firstBigBlock.ec = VisitBreakCmd(bb.ec as BreakCmd);
+ }
+ else if (bb.ec != null)
+ {
+ throw new InvalidOperationException();
+ }
+
+ return new List<BigBlock>(new BigBlock[] { firstBigBlock });
+
+ }
+
+ public virtual IfCmd VisitIfCmd(IfCmd ifCmd)
+ {
+ if(ifCmd.elseIf != null)
+ {
+ throw new InvalidOperationException();
+ }
+
+ return new IfCmd(ifCmd.tok, VisitIfGuard(ifCmd.Guard), VisitStmtList(ifCmd.thn), ifCmd.elseIf,
+ (ifCmd.elseBlock == null ? ifCmd.elseBlock : VisitStmtList(ifCmd.elseBlock)));
+
+ throw new NotImplementedException();
+ }
+
+ public virtual Expr VisitIfGuard(Expr expr)
+ {
+ return expr;
+ }
+
+ public virtual WhileCmd VisitWhileCmd(WhileCmd whileCmd)
+ {
+ return new WhileCmd(whileCmd.tok, VisitWhileGuard(whileCmd.Guard), VisitWhileInvariants(whileCmd.Invariants), VisitStmtList(whileCmd.Body));
+ }
+
+ public virtual BreakCmd VisitBreakCmd(BreakCmd breakCmd)
+ {
+ return breakCmd;
+ }
+
+
+ public virtual List<PredicateCmd> VisitWhileInvariants(List<PredicateCmd> invariants)
+ {
+ return invariants;
+ }
+
+ public virtual Expr VisitWhileGuard(Expr expr)
+ {
+ return expr;
+ }
+
+ public virtual CmdSeq VisitCmdSeq(CmdSeq cmdSeq)
+ {
+ CmdSeq result = new CmdSeq();
+ foreach (Cmd c in cmdSeq)
+ {
+ result.AddRange(VisitCmd(c));
+ }
+ return result;
+ }
+
+ public virtual CmdSeq VisitCmd(Cmd c)
+ {
+ if (c is CallCmd)
+ {
+ return VisitCallCmd(c as CallCmd);
+ }
+ if (c is AssignCmd)
+ {
+ return VisitAssignCmd(c as AssignCmd);
+ }
+ if (c is HavocCmd)
+ {
+ return VisitHavocCmd(c as HavocCmd);
+ }
+ if (c is AssertCmd)
+ {
+ return VisitAssertCmd(c as AssertCmd);
+ }
+ if (c is AssumeCmd)
+ {
+ return VisitAssumeCmd(c as AssumeCmd);
+ }
+ throw new InvalidOperationException();
+ }
+
+ public virtual CmdSeq VisitAssumeCmd(AssumeCmd assumeCmd)
+ {
+ return new CmdSeq(new Cmd[] { assumeCmd });
+ }
+
+ public virtual CmdSeq VisitAssertCmd(AssertCmd assertCmd)
+ {
+ return new CmdSeq(new Cmd[] { assertCmd });
+ }
+
+ public virtual CmdSeq VisitHavocCmd(HavocCmd havocCmd)
+ {
+ return new CmdSeq(new Cmd[] { havocCmd });
+ }
+
+ public virtual CmdSeq VisitAssignCmd(AssignCmd assignCmd)
+ {
+ return new CmdSeq(new Cmd[] { assignCmd });
+ }
+
+ public virtual CmdSeq VisitCallCmd(CallCmd callCmd)
+ {
+ return new CmdSeq(new Cmd[] { callCmd });
+ }
+
+ }
+}
diff --git a/Source/GPUVerify/VariableDualiser.cs b/Source/GPUVerify/VariableDualiser.cs
index 5cbfed99..add50f08 100644
--- a/Source/GPUVerify/VariableDualiser.cs
+++ b/Source/GPUVerify/VariableDualiser.cs
@@ -49,6 +49,29 @@ namespace GPUVerify
return base.VisitVariable(node);
}
+
+ public override Expr VisitNAryExpr(NAryExpr node)
+ {
+ // The point of this override is to avoid dualisation of certain special
+ // intrinsics that are cross-thread
+
+ if (node.Fun is FunctionCall)
+ {
+ FunctionCall call = node.Fun as FunctionCall;
+
+ if (call.Func.Name.Equals("__uniform_bv32") || call.Func.Name.Equals("__uniform_bool") ||
+ call.Func.Name.Equals("__distinct_bv32") || call.Func.Name.Equals("__distinct_bool") ||
+ call.Func.Name.Equals("__all") || call.Func.Name.Equals("__at_most_one"))
+ {
+ return node;
+ }
+
+ }
+
+ return base.VisitNAryExpr(node);
+ }
+
+
}
}
diff --git a/Source/Houdini/Checker.cs b/Source/Houdini/Checker.cs
index 3670c441..29357997 100644
--- a/Source/Houdini/Checker.cs
+++ b/Source/Houdini/Checker.cs
@@ -8,9 +8,7 @@ using System.Diagnostics.Contracts;
using System.Collections.Generic;
using Microsoft.Boogie;
using Microsoft.Boogie.VCExprAST;
-using Microsoft.Boogie.Simplify;
-using Microsoft.Boogie.Z3;
-using Microsoft.Boogie.SMTLib;
+using Microsoft.Basetypes;
using System.Collections;
using System.IO;
using System.Threading;
@@ -24,29 +22,27 @@ namespace Microsoft.Boogie.Houdini {
private VCExpr conjecture;
private ProverInterface.ErrorHandler handler;
ConditionGeneration.CounterexampleCollector collector;
- LocalVariable controlFlowVariable;
- int entryBlockId;
public HoudiniSession(VCGen vcgen, Checker checker, Program program, Implementation impl) {
descriptiveName = impl.Name;
collector = new ConditionGeneration.CounterexampleCollector();
collector.OnProgress("HdnVCGen", 0, 0, 0.0);
- if (CommandLineOptions.Clo.SoundnessSmokeTest) {
- throw new Exception("HoudiniVCGen does not support Soundness smoke test.");
- }
vcgen.ConvertCFG2DAG(impl, program);
ModelViewInfo mvInfo;
Hashtable/*TransferCmd->ReturnCmd*/ gotoCmdOrigins = vcgen.PassifyImpl(impl, program, out mvInfo);
Hashtable/*<int, Absy!>*/ label2absy;
+ var exprGen = checker.TheoremProver.Context.ExprGen;
+ VCExpr controlFlowVariableExpr = CommandLineOptions.Clo.UseLabels ? null : exprGen.Integer(BigNum.ZERO);
+
+ conjecture = vcgen.GenerateVC(impl, controlFlowVariableExpr, out label2absy, checker);
+
if (!CommandLineOptions.Clo.UseLabels) {
- controlFlowVariable = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, "@cfc", Microsoft.Boogie.Type.Int));
- impl.LocVars.Add(controlFlowVariable);
- entryBlockId = impl.Blocks[0].UniqueId;
+ VCExpr controlFlowFunctionAppl = exprGen.ControlFlowFunctionApplication(exprGen.Integer(BigNum.ZERO), exprGen.Integer(BigNum.ZERO));
+ VCExpr eqExpr = exprGen.Eq(controlFlowFunctionAppl, exprGen.Integer(BigNum.FromInt(impl.Blocks[0].UniqueId)));
+ conjecture = exprGen.Implies(eqExpr, conjecture);
}
-
- conjecture = vcgen.GenerateVC(impl, controlFlowVariable, out label2absy, checker);
if (CommandLineOptions.Clo.vcVariety == CommandLineOptions.VCVariety.Local) {
handler = new VCGen.ErrorReporterLocal(gotoCmdOrigins, label2absy, impl.Blocks, vcgen.incarnationOriginMap, collector, mvInfo, vcgen.implName2LazyInliningInfo, checker.TheoremProver.Context, program);
@@ -60,22 +56,19 @@ namespace Microsoft.Boogie.Houdini {
collector.examples.Clear();
VCExpr vc = checker.VCExprGen.Implies(axiom, conjecture);
- if (!CommandLineOptions.Clo.UseLabels) {
- var ctx = checker.TheoremProver.Context;
- var bet = ctx.BoogieExprTranslator;
- VCExpr controlFlowVariableExpr = bet.LookupVariable(controlFlowVariable);
- Contract.Assert(controlFlowVariableExpr != null);
- VCExpr controlFlowFunctionAppl = ctx.ExprGen.ControlFlowFunctionApplication(controlFlowVariableExpr, ctx.ExprGen.Integer(Microsoft.Basetypes.BigNum.ZERO));
- Contract.Assert(controlFlowFunctionAppl != null);
- vc = ctx.ExprGen.Implies(ctx.ExprGen.Eq(controlFlowFunctionAppl, ctx.ExprGen.Integer(Microsoft.Basetypes.BigNum.FromInt(entryBlockId))), vc);
+ if (CommandLineOptions.Clo.Trace) {
+ Console.WriteLine("Verifying " + descriptiveName);
}
-
DateTime now = DateTime.UtcNow;
checker.BeginCheck(descriptiveName, vc, handler);
WaitHandle.WaitAny(new WaitHandle[] { checker.ProverDone });
ProverInterface.Outcome proverOutcome = checker.ReadOutcome();
- proverTime += (DateTime.UtcNow - now).TotalSeconds;
+ double queryTime = (DateTime.UtcNow - now).TotalSeconds;
+ proverTime += queryTime;
numProverQueries++;
+ if (CommandLineOptions.Clo.Trace) {
+ Console.WriteLine("Time taken = " + queryTime);
+ }
if (proverOutcome == ProverInterface.Outcome.Invalid) {
Contract.Assume(collector.examples != null);
diff --git a/Source/Houdini/Houdini.cs b/Source/Houdini/Houdini.cs
index 9735aec1..5ac78731 100644
--- a/Source/Houdini/Houdini.cs
+++ b/Source/Houdini/Houdini.cs
@@ -8,9 +8,7 @@ using System.Diagnostics.Contracts;
using System.Collections.Generic;
using Microsoft.Boogie;
using Microsoft.Boogie.VCExprAST;
-using Microsoft.Boogie.Simplify;
using VC;
-using Microsoft.Boogie.Z3;
using System.Collections;
using System.IO;
using Microsoft.AbstractInterpretationFramework;
@@ -539,25 +537,6 @@ namespace Microsoft.Boogie.Houdini {
return outcome;
}
- private ProverInterface.Outcome VerifyCurrent(
- HoudiniSession session,
- HoudiniState current,
- Program program,
- out List<Counterexample> errors,
- out bool exc) {
- if (current.Implementation != null) {
- Implementation implementation = current.Implementation;
- if (vcgen == null)
- throw new Exception("HdnVCGen not found for implementation: " + implementation.Name);
-
- ProverInterface.Outcome outcome = TrySpinSameFunc(session, current, program, out errors, out exc);
- return outcome;
- }
- else {
- throw new Exception("VerifyCurrent has null implementation");
- }
- }
-
private bool IsOutcomeNotHoudini(ProverInterface.Outcome outcome, List<Counterexample> errors) {
switch (outcome) {
case ProverInterface.Outcome.Valid:
@@ -653,51 +632,6 @@ namespace Microsoft.Boogie.Houdini {
}
}
- private void UpdateWorkList(HoudiniState current,
- ProverInterface.Outcome outcome,
- List<Counterexample> errors) {
- Contract.Assume(current.Implementation != null);
-
- switch (outcome) {
- case ProverInterface.Outcome.Valid:
- current.WorkQueue.Dequeue();
- this.NotifyDequeue();
- break;
- case ProverInterface.Outcome.Invalid:
- Contract.Assume(errors != null);
- bool dequeue = false;
- foreach (Counterexample error in errors) {
- RefutedAnnotation refutedAnnotation = ExtractRefutedAnnotation(error);
- if (refutedAnnotation != null) {
- foreach (Implementation implementation in FindImplementationsToEnqueue(refutedAnnotation, current.Implementation)) { AddToWorkList(current, implementation); }
- UpdateAssignment(current, refutedAnnotation);
- }
- else {
- dequeue = true; //once one non-houdini error is hit dequeue?!
- }
- }
- if (dequeue) {
- current.WorkQueue.Dequeue();
- this.NotifyDequeue();
- }
- break;
- case ProverInterface.Outcome.TimeOut:
- // TODO: reset session instead of blocking timed out funcs?
- current.addToBlackList(current.Implementation.Name);
- current.WorkQueue.Dequeue();
- this.NotifyDequeue();
- break;
- case ProverInterface.Outcome.OutOfMemory:
- case ProverInterface.Outcome.Undetermined:
- current.WorkQueue.Dequeue();
- this.NotifyDequeue();
- break;
- default:
- throw new Exception("Unknown vcgen outcome");
- }
- }
-
-
private void AddRelatedToWorkList(HoudiniState current, RefutedAnnotation refutedAnnotation) {
Contract.Assume(current.Implementation != null);
foreach (Implementation implementation in FindImplementationsToEnqueue(refutedAnnotation, current.Implementation)) {
@@ -812,102 +746,6 @@ namespace Microsoft.Boogie.Houdini {
}
}
- private void PrintBadList(string kind, List<string> list) {
- if (list.Count != 0) {
- Console.WriteLine("----------------------------------------");
- Console.WriteLine("Functions: {0}", kind);
- foreach (string fname in list) {
- Console.WriteLine("\t{0}", fname);
- }
- Console.WriteLine("----------------------------------------");
- }
- }
-
- private void PrintBadOutcomes(List<string> timeouts, List<string> inconc, List<string> errors) {
- PrintBadList("TimedOut", timeouts);
- PrintBadList("Inconclusive", inconc);
- PrintBadList("Errors", errors);
- }
-
- public HoudiniOutcome VerifyProgram() {
- HoudiniOutcome outcome = VerifyProgramSameFuncFirst();
- PrintBadOutcomes(outcome.ListOfTimeouts, outcome.ListOfInconclusives, outcome.ListOfErrors);
- return outcome;
- }
-
- // Old main loop
- public HoudiniOutcome VerifyProgramUnorderedWork() {
- HoudiniState current = new HoudiniState(BuildWorkList(program), BuildAssignment(houdiniConstants.Keys));
- this.NotifyStart(program, houdiniConstants.Keys.Count);
-
- while (current.WorkQueue.Count > 0) {
- //System.GC.Collect();
- this.NotifyIteration();
-
- VCExpr axiom = BuildAxiom(current.Assignment);
- this.NotifyAssignment(current.Assignment);
-
- current.Implementation = current.WorkQueue.Peek();
- this.NotifyImplementation(current.Implementation);
-
- List<Counterexample> errors;
- HoudiniSession session;
- houdiniSessions.TryGetValue(current.Implementation, out session);
- ProverInterface.Outcome outcome = VerifyUsingAxiom(session, current.Implementation, axiom, out errors);
- this.NotifyOutcome(outcome);
-
- UpdateHoudiniOutcome(current.Outcome, current.Implementation, outcome, errors);
- if (IsOutcomeNotHoudini(outcome, errors) && !continueAtError) {
- current.WorkQueue.Dequeue();
- this.NotifyDequeue();
- FlushWorkList(current);
- }
- else
- UpdateWorkList(current, outcome, errors);
- }
- this.NotifyEnd(true);
- current.Outcome.assignment = current.Assignment;
- return current.Outcome;
- }
-
- // New main loop
- public HoudiniOutcome VerifyProgramSameFuncFirst() {
- HoudiniState current = new HoudiniState(BuildWorkList(program), BuildAssignment(houdiniConstants.Keys));
- this.NotifyStart(program, houdiniConstants.Keys.Count);
-
- while (current.WorkQueue.Count > 0) {
- bool exceptional = false;
- //System.GC.Collect();
- this.NotifyIteration();
-
- current.Implementation = current.WorkQueue.Peek();
- this.NotifyImplementation(current.Implementation);
-
- HoudiniSession session;
- houdiniSessions.TryGetValue(current.Implementation, out session);
- List<Counterexample> errors;
- ProverInterface.Outcome outcome = VerifyCurrent(session, current, program, out errors, out exceptional);
-
- // updates to worklist already done in VerifyCurrent, unless there was an exception
- if (exceptional) {
- this.NotifyOutcome(outcome);
- UpdateHoudiniOutcome(current.Outcome, current.Implementation, outcome, errors);
- if (IsOutcomeNotHoudini(outcome, errors) && !continueAtError) {
- current.WorkQueue.Dequeue();
- this.NotifyDequeue();
- FlushWorkList(current);
- }
- else {
- UpdateAssignmentWorkList(current, outcome, errors);
- }
- exceptional = false;
- }
- }
- this.NotifyEnd(true);
- current.Outcome.assignment = current.Assignment;
- return current.Outcome;
- }
-
//Clean houdini (Based on "Houdini Spec in Boogie" email 10/22/08
//Aborts when there is a violation of non-candidate assertion
//This can be used in eager mode (continueAfterError) by simply making
@@ -1100,67 +938,7 @@ namespace Microsoft.Boogie.Houdini {
return outcome;
}
- //version of TryCatchVerify that spins on the same function
- //as long as the current assignment is changing
- private ProverInterface.Outcome TrySpinSameFunc(
- HoudiniSession session,
- HoudiniState current,
- Program program,
- out List<Counterexample> errors,
- out bool exceptional) {
- Contract.Assert(current.Implementation != null);
- ProverInterface.Outcome outcome;
- errors = null;
- outcome = ProverInterface.Outcome.Undetermined;
- try {
- bool trySameFunc = true;
- bool pastFirstIter = false; //see if this new loop is even helping
-
- do {
- if (pastFirstIter) {
- //System.GC.Collect();
- this.NotifyIteration();
- }
-
- VCExpr currentAx = BuildAxiom(current.Assignment);
- this.NotifyAssignment(current.Assignment);
-
- outcome = session.Verify(checker, currentAx, out errors);
- this.NotifyOutcome(outcome);
-
- DebugRefutedCandidates(current.Implementation, errors);
- UpdateHoudiniOutcome(current.Outcome, current.Implementation, outcome, errors);
- if (!continueAtError && IsOutcomeNotHoudini(outcome, errors)) {
- current.WorkQueue.Dequeue();
- this.NotifyDequeue();
- trySameFunc = false;
- FlushWorkList(current);
- }
- else {
- trySameFunc = UpdateAssignmentWorkList(current, outcome, errors);
- //reset for the next round
- errors = null;
- outcome = ProverInterface.Outcome.Undetermined;
- }
- pastFirstIter = true;
- } while (trySameFunc && current.WorkQueue.Count > 0);
-
- }
- catch (VCGenException e) {
- Contract.Assume(e != null);
- NotifyException("VCGen");
- exceptional = true;
- return outcome;
- }
- catch (UnexpectedProverOutputException upo) {
- Contract.Assume(upo != null);
- NotifyException("UnexpectedProverOutput");
- exceptional = true;
- return outcome;
- }
- exceptional = false;
- return outcome;
- }
+
//Similar to TrySpinSameFunc except no Candidate logic
private ProverInterface.Outcome HoudiniVerifyCurrentAux(
@@ -1193,9 +971,6 @@ namespace Microsoft.Boogie.Houdini {
this.NotifyAssignment(current.Assignment);
//check the VC with the current assignment
- if (CommandLineOptions.Clo.Trace) {
- Console.WriteLine("Verifying " + session.descriptiveName);
- }
outcome = session.Verify(checker, currentAx, out errors);
this.NotifyOutcome(outcome);
@@ -1234,10 +1009,26 @@ namespace Microsoft.Boogie.Houdini {
public enum HoudiniOutcomeKind { Done, FatalError, VerificationCompleted }
public class VCGenOutcome {
- public ProverInterface.Outcome outcome;
+ public VCGen.Outcome outcome;
public List<Counterexample> errors;
public VCGenOutcome(ProverInterface.Outcome outcome, List<Counterexample> errors) {
- this.outcome = outcome;
+ switch (outcome) {
+ case ProverInterface.Outcome.Invalid:
+ this.outcome = ConditionGeneration.Outcome.Errors;
+ break;
+ case ProverInterface.Outcome.OutOfMemory:
+ this.outcome = ConditionGeneration.Outcome.OutOfMemory;
+ break;
+ case ProverInterface.Outcome.TimeOut:
+ this.outcome = ConditionGeneration.Outcome.TimedOut;
+ break;
+ case ProverInterface.Outcome.Undetermined:
+ this.outcome = ConditionGeneration.Outcome.Inconclusive;
+ break;
+ case ProverInterface.Outcome.Valid:
+ this.outcome = ConditionGeneration.Outcome.Correct;
+ break;
+ }
this.errors = errors;
}
}
@@ -1252,7 +1043,7 @@ namespace Microsoft.Boogie.Houdini {
// statistics
- private int CountResults(ProverInterface.Outcome outcome) {
+ private int CountResults(VCGen.Outcome outcome) {
int outcomeCount = 0;
foreach (VCGenOutcome verifyOutcome in implementationOutcomes.Values) {
if (verifyOutcome.outcome == outcome)
@@ -1261,7 +1052,7 @@ namespace Microsoft.Boogie.Houdini {
return outcomeCount;
}
- private List<string> ListOutcomeMatches(ProverInterface.Outcome outcome) {
+ private List<string> ListOutcomeMatches(VCGen.Outcome outcome) {
List<string> result = new List<string>();
foreach (KeyValuePair<string, VCGenOutcome> kvpair in implementationOutcomes) {
if (kvpair.Value.outcome == outcome)
@@ -1272,37 +1063,37 @@ namespace Microsoft.Boogie.Houdini {
public int ErrorCount {
get {
- return CountResults(ProverInterface.Outcome.Invalid);
+ return CountResults(VCGen.Outcome.Errors);
}
}
public int Verified {
get {
- return CountResults(ProverInterface.Outcome.Valid);
+ return CountResults(VCGen.Outcome.Correct);
}
}
public int Inconclusives {
get {
- return CountResults(ProverInterface.Outcome.Undetermined);
+ return CountResults(VCGen.Outcome.Inconclusive);
}
}
public int TimeOuts {
get {
- return CountResults(ProverInterface.Outcome.TimeOut);
+ return CountResults(VCGen.Outcome.TimedOut);
}
}
public List<string> ListOfTimeouts {
get {
- return ListOutcomeMatches(ProverInterface.Outcome.TimeOut);
+ return ListOutcomeMatches(VCGen.Outcome.TimedOut);
}
}
public List<string> ListOfInconclusives {
get {
- return ListOutcomeMatches(ProverInterface.Outcome.Undetermined);
+ return ListOutcomeMatches(VCGen.Outcome.Inconclusive);
}
}
public List<string> ListOfErrors {
get {
- return ListOutcomeMatches(ProverInterface.Outcome.Invalid);
+ return ListOutcomeMatches(VCGen.Outcome.Errors);
}
}
}
diff --git a/Source/Houdini/Houdini.csproj b/Source/Houdini/Houdini.csproj
index c4d4cb8a..af1755a3 100644
--- a/Source/Houdini/Houdini.csproj
+++ b/Source/Houdini/Houdini.csproj
@@ -106,18 +106,10 @@
<Project>{FCD3AC7F-9DFD-46C8-AB1E-09F0B0F16DC5}</Project>
<Name>ParserHelper</Name>
</ProjectReference>
- <ProjectReference Include="..\Provers\Simplify\Simplify.csproj">
- <Project>{FEE9F01B-9722-4A76-A24B-72A4016DFA8E}</Project>
- <Name>Simplify</Name>
- </ProjectReference>
<ProjectReference Include="..\Provers\SMTLib\SMTLib.csproj">
<Project>{9B163AA3-36BC-4AFB-88AB-79BC9E97E401}</Project>
<Name>SMTLib</Name>
</ProjectReference>
- <ProjectReference Include="..\Provers\Z3\Z3.csproj">
- <Project>{BB49B90B-BE21-4BE8-85BA-359FDB55F4DF}</Project>
- <Name>Z3</Name>
- </ProjectReference>
<ProjectReference Include="..\VCExpr\VCExpr.csproj">
<Project>{56FFDBCA-7D14-43B8-A6CA-22A20E417EE1}</Project>
<Name>VCExpr</Name>
diff --git a/Source/Provers/SMTLib/Inspector.cs b/Source/Provers/SMTLib/Inspector.cs
index 4126c169..362502f3 100644
--- a/Source/Provers/SMTLib/Inspector.cs
+++ b/Source/Provers/SMTLib/Inspector.cs
@@ -11,7 +11,6 @@ using System.Collections.Generic;
using System.Diagnostics.Contracts;
//using util;
using Microsoft.Boogie;
-using Microsoft.Boogie.Simplify;
using Microsoft.Basetypes;
using Microsoft.Boogie.VCExprAST;
diff --git a/Source/Provers/SMTLib/ProverInterface.cs b/Source/Provers/SMTLib/ProverInterface.cs
index 657603d0..6ef3778d 100644
--- a/Source/Provers/SMTLib/ProverInterface.cs
+++ b/Source/Provers/SMTLib/ProverInterface.cs
@@ -17,12 +17,11 @@ using Microsoft.Boogie;
using Microsoft.Boogie.VCExprAST;
using Microsoft.Boogie.Clustering;
using Microsoft.Boogie.TypeErasure;
-using Microsoft.Boogie.Simplify;
using System.Text;
namespace Microsoft.Boogie.SMTLib
{
- public class SMTLibProcessTheoremProver : ApiProverInterface
+ public class SMTLibProcessTheoremProver : ProverInterface
{
private readonly SMTLibProverContext ctx;
private readonly VCExpressionGenerator gen;
@@ -94,7 +93,6 @@ namespace Microsoft.Boogie.SMTLib
PrepareCommon();
}
prevOutcomeAvailable = false;
- pendingPop = false;
}
void SetupProcess()
@@ -285,15 +283,6 @@ namespace Microsoft.Boogie.SMTLib
Process.Close();
}
- string controlFlowVariable;
-
- private VCExpr ArgumentZero(VCExpr vc) {
- VCExprNAry naryExpr = vc as VCExprNAry;
- if (naryExpr == null)
- return null;
- return naryExpr[0];
- }
-
public override void BeginCheck(string descriptiveName, VCExpr vc, ErrorHandler handler)
{
//Contract.Requires(descriptiveName != null);
@@ -307,9 +296,6 @@ namespace Microsoft.Boogie.SMTLib
currentLogFile.Write(common.ToString());
}
- if (!CommandLineOptions.Clo.UseLabels)
- controlFlowVariable = VCExpr2String(ArgumentZero(ArgumentZero(ArgumentZero(vc))),1);
-
PrepareCommon();
string vcString = "(assert (not\n" + VCExpr2String(vc, 1) + "\n))";
FlushAxioms();
@@ -395,7 +381,19 @@ namespace Microsoft.Boogie.SMTLib
[NoDefaultContract]
public override Outcome CheckOutcome(ErrorHandler handler)
- { //Contract.Requires(handler != null);
+ {
+ Contract.EnsuresOnThrow<UnexpectedProverOutputException>(true);
+
+ var result = CheckOutcomeCore(handler);
+ SendThisVC("(pop 1)");
+ FlushLogFile();
+
+ return result;
+ }
+
+ [NoDefaultContract]
+ public override Outcome CheckOutcomeCore(ErrorHandler handler)
+ {
Contract.EnsuresOnThrow<UnexpectedProverOutputException>(true);
var result = Outcome.Undetermined;
@@ -413,40 +411,47 @@ namespace Microsoft.Boogie.SMTLib
var globalResult = Outcome.Undetermined;
- while (errorsLeft-- > 0) {
+ while (true) {
+ errorsLeft--;
string[] labels = null;
result = GetResponse();
if (globalResult == Outcome.Undetermined)
globalResult = result;
- if (result == Outcome.Invalid && options.UseZ3) {
- labels = GetLabelsInfo(handler);
+ if (result == Outcome.Invalid) {
+ IList<string> xlabels;
+ if (CommandLineOptions.Clo.UseLabels) {
+ labels = GetLabelsInfo();
+ xlabels = labels.Select(a => a.Replace("@", "").Replace("+", "")).ToList();
+ }
+ else {
+ labels = CalculatePath(0);
+ xlabels = labels;
+ }
+ ErrorModel errorModel = GetErrorModel();
+ handler.OnModel(xlabels, errorModel);
}
- if (labels == null) break;
+ if (labels == null || errorsLeft == 0) break;
- var negLabels = labels.Where(l => l.StartsWith("@")).ToArray();
- var posLabels = labels.Where(l => !l.StartsWith("@"));
- Func<string, string> lbl = (s) => SMTLibNamer.QuoteId(SMTLibNamer.LabelVar(s));
- if (!options.MultiTraces)
- posLabels = Enumerable.Empty<string>();
- var conjuncts = posLabels.Select(s => "(not " + lbl(s) + ")").Concat(negLabels.Select(lbl)).ToArray();
- var expr = conjuncts.Length == 1 ? conjuncts[0] : ("(or " + conjuncts.Concat(" ") + ")");
- if (errorsLeft > 0) {
+ if (CommandLineOptions.Clo.UseLabels) {
+ var negLabels = labels.Where(l => l.StartsWith("@")).ToArray();
+ var posLabels = labels.Where(l => !l.StartsWith("@"));
+ Func<string, string> lbl = (s) => SMTLibNamer.QuoteId(SMTLibNamer.LabelVar(s));
+ if (!options.MultiTraces)
+ posLabels = Enumerable.Empty<string>();
+ var conjuncts = posLabels.Select(s => "(not " + lbl(s) + ")").Concat(negLabels.Select(lbl)).ToArray();
+ var expr = conjuncts.Length == 1 ? conjuncts[0] : ("(or " + conjuncts.Concat(" ") + ")");
SendThisVC("(assert " + expr + ")");
SendThisVC("(check-sat)");
}
- }
-
- if (CommandLineOptions.Clo.StratifiedInlining == 0)
- {
- SendThisVC("(pop 1)");
- }
- else if (CommandLineOptions.Clo.StratifiedInlining > 0 && pendingPop)
- {
- pendingPop = false;
- SendThisVC("(pop 1)");
+ else {
+ string source = labels[labels.Length - 2];
+ string target = labels[labels.Length - 1];
+ SendThisVC("(assert (not (= (ControlFlow 0 " + source + ") (- " + target + "))))");
+ SendThisVC("(check-sat)");
+ }
}
FlushLogFile();
@@ -461,100 +466,91 @@ namespace Microsoft.Boogie.SMTLib
}
}
- private string[] CalculatePath() {
- SendThisVC("(get-value ((ControlFlow " + controlFlowVariable + " 0)))");
+ public override string[] CalculatePath(int controlFlowConstant) {
+ SendThisVC("(get-value ((ControlFlow " + controlFlowConstant + " 0)))");
var path = new List<string>();
while (true) {
var resp = Process.GetProverResponse();
- if (resp == null)
- break;
+ if (resp == null) break;
if (!(resp.Name == "" && resp.ArgCount == 1)) break;
resp = resp.Arguments[0];
if (!(resp.Name == "" && resp.ArgCount == 2)) break;
resp = resp.Arguments[1];
var v = resp.Name;
- if (v == "-" && resp.ArgCount == 1)
- v += resp.Arguments[0].Name;
- else if (resp.ArgCount != 0)
+ if (v == "-" && resp.ArgCount == 1) {
+ v = resp.Arguments[0].Name;
+ path.Add(v);
+ break;
+ }
+ else if (resp.ArgCount != 0)
break;
- if (v.StartsWith("-")) {
- path.Add("@" + v.Substring(1));
+ path.Add(v);
+ SendThisVC("(get-value ((ControlFlow " + controlFlowConstant + " " + v + ")))");
+ }
+ return path.ToArray();
+ }
+
+ private ErrorModel GetErrorModel() {
+ if (!options.ExpectingModel())
+ return null;
+ SendThisVC("(get-model)");
+ Process.Ping();
+ Model theModel = null;
+ while (true) {
+ var resp = Process.GetProverResponse();
+ if (resp == null || Process.IsPong(resp))
break;
+ if (theModel != null)
+ HandleProverError("Expecting only one model but got many");
+
+ string modelStr = null;
+ if (resp.Name == "model" && resp.ArgCount >= 1) {
+ modelStr = resp[0].Name;
+ }
+ else if (resp.ArgCount == 0 && resp.Name.Contains("->")) {
+ modelStr = resp.Name;
}
else {
- path.Add("+" + v);
+ HandleProverError("Unexpected prover response getting model: " + resp.ToString());
+ }
+ List<Model> models = null;
+ try {
+ models = Model.ParseModels(new StringReader("Z3 error model: \n" + modelStr));
}
- SendThisVC("(get-value ((ControlFlow " + controlFlowVariable + " " + v + ")))");
+ catch (ArgumentException exn) {
+ HandleProverError("Model parsing error: " + exn.Message);
+ }
+ if (models == null)
+ HandleProverError("Could not parse any models");
+ else if (models.Count == 0)
+ HandleProverError("Could not parse any models");
+ else if (models.Count > 1)
+ HandleProverError("Expecting only one model but got many");
+ else
+ theModel = models[0];
}
- return path.ToArray();
+ return new ErrorModel(theModel);
}
- private string[] GetLabelsInfo(ErrorHandler handler)
+ private string[] GetLabelsInfo()
{
- if (CommandLineOptions.Clo.UseLabels)
- SendThisVC("(labels)");
- if (options.ExpectingModel())
- SendThisVC("(get-model)");
+ SendThisVC("(labels)");
Process.Ping();
- List<string> labelNums = null;
- Model theModel = null;
string[] res = null;
-
while (true) {
var resp = Process.GetProverResponse();
if (resp == null || Process.IsPong(resp))
break;
+ if (res != null)
+ HandleProverError("Expecting only one sequence of labels but got many");
if (resp.Name == "labels" && resp.ArgCount >= 1) {
- var labels = resp.Arguments.Select(a => a.Name.Replace("|", "")).ToArray();
- res = labels;
- if (labelNums != null) HandleProverError("Got multiple :labels responses");
- labelNums = labels.Select(a => a.Replace("@", "").Replace("+", "")).ToList();
- } else {
- string modelStr = null;
- if (resp.Name == "model" && resp.ArgCount >= 1) {
- modelStr = resp[0].Name;
- } else if (resp.ArgCount == 0 && resp.Name.Contains("->")) {
- modelStr = resp.Name;
- }
-
- if (modelStr != null) {
- List<Model> models = null;
- try {
- models = Model.ParseModels(new StringReader("Z3 error model: \n" + modelStr));
- } catch (ArgumentException exn) {
- HandleProverError("Model parsing error: " + exn.Message);
- }
-
- if (models != null) {
- if (models.Count == 0) HandleProverError("Could not parse any models");
- else {
- if (models.Count > 1) HandleProverError("Expecting only one model, got multiple");
- if (theModel != null) HandleProverError("Got multiple :model responses");
- theModel = models[0];
- }
- }
- } else {
- HandleProverError("Unexpected prover response (getting labels/model): " + resp.ToString());
- }
+ res = resp.Arguments.Select(a => a.Name.Replace("|", "")).ToArray();
+ }
+ else {
+ HandleProverError("Unexpected prover response getting labels: " + resp.ToString());
}
}
-
- if (!CommandLineOptions.Clo.UseLabels) {
- res = CalculatePath();
- if (res.Length == 0)
- res = null;
- else
- labelNums = res.Select(a => a.Replace("@", "").Replace("+", "")).ToList();
- }
-
- if (labelNums != null) {
- ErrorModel m = null;
- if (theModel != null)
- m = new ErrorModel(theModel);
- handler.OnModel(labelNums, m);
- }
-
return res;
}
@@ -767,7 +763,6 @@ namespace Microsoft.Boogie.SMTLib
throw new NotImplementedException();
}
- // For implementing ApiProverInterface
public override void Assert(VCExpr vc, bool polarity)
{
string a = "";
@@ -790,7 +785,7 @@ namespace Microsoft.Boogie.SMTLib
public override void Check()
{
- Contract.Assert(pendingPop == false && prevOutcomeAvailable == false);
+ Contract.Assert(prevOutcomeAvailable == false);
PrepareCommon();
SendThisVC("(check-sat)");
@@ -806,15 +801,13 @@ namespace Microsoft.Boogie.SMTLib
/// Extra state for ApiChecker (used by stratifiedInlining)
/// </summary>
bool prevOutcomeAvailable;
- bool pendingPop;
Outcome prevOutcome;
static int nameCounter = 0;
public override void CheckAssumptions(List<VCExpr> assumptions, out List<int> unsatCore)
{
- Contract.Assert(pendingPop == false && prevOutcomeAvailable == false);
+ Contract.Assert(prevOutcomeAvailable == false);
- Push();
unsatCore = new List<int>();
// Name the assumptions
@@ -835,7 +828,6 @@ namespace Microsoft.Boogie.SMTLib
prevOutcomeAvailable = true;
if (prevOutcome != Outcome.Valid)
{
- pendingPop = true;
return;
}
Contract.Assert(usingUnsatCore, "SMTLib prover not setup for computing unsat cores");
@@ -845,8 +837,6 @@ namespace Microsoft.Boogie.SMTLib
if(resp.Name != "") unsatCore.Add(nameToAssumption[resp.Name]);
foreach (var s in resp.Arguments) unsatCore.Add(nameToAssumption[s.Name]);
- Pop();
-
FlushLogFile();
}
diff --git a/Source/Provers/SMTLib/SMTLib.csproj b/Source/Provers/SMTLib/SMTLib.csproj
index f4cdbb14..3dc042a6 100644
--- a/Source/Provers/SMTLib/SMTLib.csproj
+++ b/Source/Provers/SMTLib/SMTLib.csproj
@@ -191,10 +191,6 @@
<Project>{E1F10180-C7B9-4147-B51F-FA1B701966DC}</Project>
<Name>VCGeneration</Name>
</ProjectReference>
- <ProjectReference Include="..\Simplify\Simplify.csproj">
- <Project>{FEE9F01B-9722-4A76-A24B-72A4016DFA8E}</Project>
- <Name>Simplify</Name>
- </ProjectReference>
</ItemGroup>
<ItemGroup>
<Folder Include="Properties\" />
diff --git a/Source/Provers/TPTP/TPTP.csproj b/Source/Provers/TPTP/TPTP.csproj
index 564b33f3..882d8009 100644
--- a/Source/Provers/TPTP/TPTP.csproj
+++ b/Source/Provers/TPTP/TPTP.csproj
@@ -116,10 +116,6 @@
<Project>{E1F10180-C7B9-4147-B51F-FA1B701966DC}</Project>
<Name>VCGeneration</Name>
</ProjectReference>
- <ProjectReference Include="..\Simplify\Simplify.csproj">
- <Project>{FEE9F01B-9722-4A76-A24B-72A4016DFA8E}</Project>
- <Name>Simplify</Name>
- </ProjectReference>
</ItemGroup>
<ItemGroup>
<Folder Include="Properties\" />
diff --git a/Source/Provers/Z3api/ProverLayer.cs b/Source/Provers/Z3api/ProverLayer.cs
index 947d4eae..3b7b8f43 100644
--- a/Source/Provers/Z3api/ProverLayer.cs
+++ b/Source/Provers/Z3api/ProverLayer.cs
@@ -8,7 +8,7 @@ using Microsoft.Boogie.AbstractInterpretation;
using Microsoft.Boogie;
using Microsoft.Boogie.Z3;
using Microsoft.Boogie.VCExprAST;
-using Microsoft.Boogie.Simplify;
+using System.Diagnostics.Contracts;
using TypeAst = System.IntPtr;
using TermAst = System.IntPtr;
@@ -19,7 +19,146 @@ using PatternAst = System.IntPtr;
namespace Microsoft.Boogie.Z3
{
- public class Z3apiProcessTheoremProver : ApiProverInterface
+ public class Z3InstanceOptions : ProverOptions {
+ public int Timeout { get { return TimeLimit / 1000; } }
+ public int Lets {
+ get {
+ Contract.Ensures(0 <= Contract.Result<int>() && Contract.Result<int>() < 4);
+ return CommandLineOptions.Clo.Z3lets;
+ }
+ }
+ public bool DistZ3 = false;
+ public string ExeName = "z3.exe";
+ public bool InverseImplies = false;
+ public string Inspector = null;
+ public bool OptimizeForBv = false;
+
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(ExeName != null);
+ }
+
+ protected override bool Parse(string opt) {
+ //Contract.Requires(opt!=null);
+ return ParseBool(opt, "REVERSE_IMPLIES", ref InverseImplies) ||
+ ParseString(opt, "INSPECTOR", ref Inspector) ||
+ ParseBool(opt, "DIST", ref DistZ3) ||
+ ParseBool(opt, "OPTIMIZE_FOR_BV", ref OptimizeForBv) ||
+ base.Parse(opt);
+ }
+
+ public override void PostParse() {
+ base.PostParse();
+
+ if (DistZ3) {
+ ExeName = "z3-dist.exe";
+ CommandLineOptions.Clo.RestartProverPerVC = true;
+ }
+ }
+
+ public override string Help {
+ get {
+ return
+@"
+Z3-specific options:
+~~~~~~~~~~~~~~~~~~~~
+INSPECTOR=<string> Use the specified Z3Inspector binary.
+OPTIMIZE_FOR_BV=<bool> Optimize Z3 options for bitvector reasoning, and not quantifier instantiation. Defaults to false.
+
+Obscure options:
+~~~~~~~~~~~~~~~~
+DIST=<bool> Use z3-dist.exe binary.
+REVERSE_IMPLIES=<bool> Encode P==>Q as Q||!P.
+
+" + base.Help;
+ // DIST requires non-public binaries
+ }
+ }
+ }
+
+ public class Z3LineariserOptions : LineariserOptions {
+ private readonly Z3InstanceOptions opts;
+
+ [ContractInvariantMethod]
+ void ObjectInvariant() {
+ Contract.Invariant(opts != null);
+ }
+
+
+ public Z3LineariserOptions(bool asTerm, Z3InstanceOptions opts, List<VCExprVar/*!>!*/> letVariables)
+ : base(asTerm) {
+ Contract.Requires(opts != null);
+ Contract.Requires(cce.NonNullElements(letVariables));
+
+ this.opts = opts;
+ this.LetVariablesAttr = letVariables;
+ }
+
+ public override bool UseWeights {
+ get {
+ return true;
+ }
+ }
+
+ public override bool UseTypes {
+ get {
+ return true;
+ }
+ }
+
+ public override bool QuantifierIds {
+ get {
+ return true;
+ }
+ }
+
+ public override bool InverseImplies {
+ get {
+ return opts.InverseImplies;
+ }
+ }
+
+ public override LineariserOptions SetAsTerm(bool newVal) {
+ Contract.Ensures(Contract.Result<LineariserOptions>() != null);
+
+ if (newVal == AsTerm)
+ return this;
+ return new Z3LineariserOptions(newVal, opts, LetVariables);
+ }
+
+ // variables representing formulas in let-bindings have to be
+ // printed in a different way than other variables
+ private readonly List<VCExprVar/*!>!*/> LetVariablesAttr;
+ public override List<VCExprVar/*!>!*/> LetVariables {
+ get {
+ Contract.Ensures(cce.NonNullElements(Contract.Result<List<VCExprVar>>()));
+
+ return LetVariablesAttr;
+ }
+ }
+
+ public override LineariserOptions AddLetVariable(VCExprVar furtherVar) {
+ //Contract.Requires(furtherVar != null);
+ Contract.Ensures(Contract.Result<LineariserOptions>() != null);
+
+ List<VCExprVar/*!>!*/> allVars = new List<VCExprVar/*!*/>();
+ allVars.AddRange(LetVariables);
+ allVars.Add(furtherVar);
+ return new Z3LineariserOptions(AsTerm, opts, allVars);
+ }
+
+ public override LineariserOptions AddLetVariables(List<VCExprVar/*!>!*/> furtherVars) {
+ //Contract.Requires(furtherVars != null);
+ Contract.Ensures(Contract.Result<LineariserOptions>() != null);
+
+ List<VCExprVar/*!>!*/> allVars = new List<VCExprVar/*!*/>();
+ allVars.AddRange(LetVariables);
+ allVars.AddRange(furtherVars);
+ return new Z3LineariserOptions(AsTerm, opts, allVars);
+ }
+ }
+
+ public class Z3apiProcessTheoremProver : ProverInterface
{
public Z3apiProcessTheoremProver(Z3InstanceOptions opts, DeclFreeProverContext ctxt)
{
@@ -152,6 +291,16 @@ namespace Microsoft.Boogie.Z3
return outcome;
}
+ public override Outcome CheckOutcomeCore(ErrorHandler handler) {
+ if (outcome == Outcome.Invalid) {
+ foreach (Z3ErrorModelAndLabels z3LabelModel in z3LabelModels) {
+ List<string> unprefixedLabels = RemovePrefixes(z3LabelModel.RelevantLabels);
+ handler.OnModel(unprefixedLabels, z3LabelModel.ErrorModel);
+ }
+ }
+ return outcome;
+ }
+
private List<string> RemovePrefixes(List<string> labels)
{
List<string> result = new List<string>();
diff --git a/Source/Provers/Z3api/Z3api.csproj b/Source/Provers/Z3api/Z3api.csproj
index 94184957..7c481438 100644
--- a/Source/Provers/Z3api/Z3api.csproj
+++ b/Source/Provers/Z3api/Z3api.csproj
@@ -162,14 +162,6 @@
<Project>{E1F10180-C7B9-4147-B51F-FA1B701966DC}</Project>
<Name>VCGeneration</Name>
</ProjectReference>
- <ProjectReference Include="..\Simplify\Simplify.csproj">
- <Project>{FEE9F01B-9722-4A76-A24B-72A4016DFA8E}</Project>
- <Name>Simplify</Name>
- </ProjectReference>
- <ProjectReference Include="..\Z3\Z3.csproj">
- <Project>{BB49B90B-BE21-4BE8-85BA-359FDB55F4DF}</Project>
- <Name>Z3</Name>
- </ProjectReference>
</ItemGroup>
<ItemGroup>
<Compile Include="..\..\version.cs">
diff --git a/Source/VCGeneration/Check.cs b/Source/VCGeneration/Check.cs
index 9b7b6e36..d74497c0 100644
--- a/Source/VCGeneration/Check.cs
+++ b/Source/VCGeneration/Check.cs
@@ -734,7 +734,7 @@ namespace Microsoft.Boogie {
Undetermined
}
public class ErrorHandler {
- public virtual void OnModel(IList<string>/*!>!*/ labels, ErrorModel errModel) {
+ public virtual void OnModel(IList<string> labels, ErrorModel errModel) {
Contract.Requires(cce.NonNullElements(labels));
}
@@ -743,7 +743,6 @@ namespace Microsoft.Boogie {
}
public virtual void OnProverWarning(string message)
- //modifies Console.Out.*, Console.Error.*;
{
Contract.Requires(message != null);
switch (CommandLineOptions.Clo.PrintProverWarnings) {
@@ -761,7 +760,6 @@ namespace Microsoft.Boogie {
}
}
-
public virtual Absy Label2Absy(string label) {
Contract.Requires(label != null);
Contract.Ensures(Contract.Result<Absy>() != null);
@@ -772,6 +770,9 @@ namespace Microsoft.Boogie {
public abstract void BeginCheck(string descriptiveName, VCExpr vc, ErrorHandler handler);
[NoDefaultContract]
public abstract Outcome CheckOutcome(ErrorHandler handler);
+ public virtual string[] CalculatePath(int controlFlowConstant) {
+ throw new System.NotImplementedException();
+ }
public virtual void LogComment(string comment) {
Contract.Requires(comment != null);
}
@@ -804,6 +805,44 @@ namespace Microsoft.Boogie {
throw new NotImplementedException();
}
+ // (assert vc)
+ public virtual void Assert(VCExpr vc, bool polarity)
+ {
+ throw new NotImplementedException();
+ }
+
+ // (assert implicit-axioms)
+ public virtual void AssertAxioms()
+ {
+ throw new NotImplementedException();
+ }
+
+ // (check-sat)
+ public virtual void Check()
+ {
+ throw new NotImplementedException();
+ }
+
+ // (check-sat + get-unsat-core)
+ public virtual void CheckAssumptions(List<VCExpr> assumptions, out List<int> unsatCore)
+ {
+ throw new NotImplementedException();
+ }
+
+ public virtual Outcome CheckOutcomeCore(ErrorHandler handler)
+ {
+ throw new NotImplementedException();
+ }
+
+ // (push 1)
+ public virtual void Push()
+ {
+ throw new NotImplementedException();
+ }
+
+ // Set theorem prover timeout for the next "check-sat"
+ public virtual void SetTimeOut(int ms)
+ { }
public abstract ProverContext Context {
get;
@@ -812,6 +851,7 @@ namespace Microsoft.Boogie {
get;
}
}
+
public class ProverInterfaceContracts : ProverInterface {
public override ProverContext Context {
get {
@@ -840,17 +880,6 @@ namespace Microsoft.Boogie {
}
}
- // Exposes an api in line with z3's api
- public abstract class ApiProverInterface : ProverInterface
- {
- public abstract void Assert(VCExpr vc, bool polarity);
- public abstract void AssertAxioms();
- public abstract void Check();
- public abstract void CheckAssumptions(List<VCExpr> assumptions, out List<int> unsatCore);
- public abstract void Push();
- public virtual void SetTimeOut(int ms) { }
- }
-
public class ProverException : Exception {
public ProverException(string s)
: base(s) {
diff --git a/Source/VCGeneration/StratifiedVC.cs b/Source/VCGeneration/StratifiedVC.cs
index e0d7b4a7..b9b0928c 100644
--- a/Source/VCGeneration/StratifiedVC.cs
+++ b/Source/VCGeneration/StratifiedVC.cs
@@ -87,7 +87,6 @@ namespace VC
{
Contract.Invariant(cce.NonNullElements(privateVars));
Contract.Invariant(cce.NonNullElements(interfaceExprVars));
- Contract.Invariant(cce.NonNullElements(interfaceExprVars));
}
public bool initialized;
@@ -127,9 +126,6 @@ namespace VC
{
StratifiedInliningInfo info = new StratifiedInliningInfo(impl, program, checker.TheoremProver.Context, QuantifierExpr.GetNextSkolemId());
implName2StratifiedInliningInfo[impl.Name] = info;
- // We don't need controlFlowVariable for stratified Inlining
- //impl.LocVars.Add(info.controlFlowVariable);
-
ExprSeq exprs = new ExprSeq();
foreach (Variable v in program.GlobalVariables())
@@ -209,10 +205,18 @@ namespace VC
VCExpressionGenerator gen = checker.VCExprGen;
Contract.Assert(gen != null);
+ var ctx = checker.TheoremProver.Context;
+ var exprGen = ctx.ExprGen;
+ var bet = ctx.BoogieExprTranslator;
+ VCExpr controlFlowVariableExpr = CommandLineOptions.Clo.UseLabels ? null : bet.LookupVariable(info.controlFlowVariable);
- VCExpr vcexpr = gen.Not(GenerateVC(impl, null, out label2absy, checker));
+ VCExpr vcexpr = gen.Not(GenerateVC(impl, controlFlowVariableExpr, out label2absy, checker));
Contract.Assert(vcexpr != null);
-
+ if (!CommandLineOptions.Clo.UseLabels) {
+ VCExpr controlFlowFunctionAppl = exprGen.ControlFlowFunctionApplication(controlFlowVariableExpr, exprGen.Integer(BigNum.ZERO));
+ VCExpr eqExpr = exprGen.Eq(controlFlowFunctionAppl, exprGen.Integer(BigNum.FromInt(impl.Blocks[0].UniqueId)));
+ vcexpr = exprGen.And(eqExpr, vcexpr);
+ }
info.label2absy = label2absy;
info.mvInfo = mvInfo;
@@ -272,7 +276,7 @@ namespace VC
Dictionary<string, List<CallSite>> calleeToCallSites;
Dictionary<string, List<CallSite>> callerToCallSites;
- private void CreateProcedureCopies(Implementation impl, Program program, StratifiedCheckerInterface checker, VCExpr vcMain) {
+ private void CreateProcedureCopies(Implementation impl, Program program, ApiChecker checker, VCExpr vcMain) {
interfaceVarCopies = new Dictionary<string, List<VCExprVar>>();
privateVarCopies = new Dictionary<string, List<VCExprVar>>();
procVcCopies = new Dictionary<string, VCExpr>();
@@ -556,14 +560,14 @@ namespace VC
}
public class BoundingVCMutator : MutatingVCExprVisitor<bool> {
- StratifiedCheckerInterface checker;
+ ApiChecker checker;
string implName;
Dictionary<string, List<VCExprVar>> interfaceVarCopies;
Dictionary<string, List<CallSite>> calleeToCallSites;
Dictionary<string, List<CallSite>> callerToCallSites;
public BoundingVCMutator(
- StratifiedCheckerInterface checker,
+ ApiChecker checker,
string implName,
Dictionary<string, List<VCExprVar>> interfaceVarCopies,
Dictionary<string, List<CallSite>> calleeToCallSites,
@@ -626,7 +630,8 @@ namespace VC
} // end BoundingVCMutator
- private void CreateProcedureCopy(StratifiedInliningInfo info, StratifiedCheckerInterface checker) {
+ private void CreateProcedureCopy(StratifiedInliningInfo info, ApiChecker checker)
+ {
var translator = checker.underlyingChecker.TheoremProver.Context.BoogieExprTranslator;
var Gen = checker.underlyingChecker.VCExprGen;
var expr = info.vcexpr;
@@ -1023,148 +1028,7 @@ namespace VC
}
- // Unifies the interface between standard checker and z3api-based checker
- abstract public class StratifiedCheckerInterface
- {
- // Underlying checker
- public Checker underlyingChecker;
- // Statistics
- public int numQueries;
-
- abstract public Outcome CheckVC();
- abstract public void Push();
- abstract public void Pop();
- abstract public void AddAxiom(VCExpr vc);
- abstract public void LogComment(string str);
- abstract public void updateMainVC(VCExpr vcMain);
- virtual public Outcome CheckAssumptions(List<VCExpr> assumptions, out List<int> unsatCore)
- {
- Outcome ret;
-
- unsatCore = new List<int>();
- for (int i = 0; i < assumptions.Count; i++)
- unsatCore.Add(i);
-
- if (assumptions.Count == 0)
- {
- return CheckVC();
- }
-
- Push();
-
- foreach (var a in assumptions)
- {
- AddAxiom(a);
- }
- ret = CheckVC();
-
- Pop();
-
- return ret;
- }
- virtual public void SetTimeOut(int msec)
- {
- // default behavior is to ignore this timeout
- }
- }
-
- public class NormalChecker : StratifiedCheckerInterface
- {
- // The VC of main
- public VCExpr vcMain;
- // Error reporter (stores models)
- public ProverInterface.ErrorHandler reporter;
- // The theorem prover interface
- public Checker checker;
- // stores the number of axioms pushed since pervious backtracking point
- private List<int> numAxiomsPushed;
-
- public NormalChecker(VCExpr vcMain, ProverInterface.ErrorHandler reporter, Checker checker)
- {
- this.vcMain = vcMain;
- this.reporter = reporter;
- this.checker = checker;
- this.underlyingChecker = checker;
- numAxiomsPushed = new List<int>();
- numQueries = 0;
- }
-
- public override void updateMainVC(VCExpr vcMain)
- {
- this.vcMain = vcMain;
- }
-
- public override Outcome CheckVC()
- {
- Contract.Requires(vcMain != null);
- Contract.Requires(reporter != null);
- Contract.Requires(checker != null);
- Contract.EnsuresOnThrow<UnexpectedProverOutputException>(true);
-
- checker.TheoremProver.FlushAxiomsToTheoremProver();
- checker.BeginCheck("the_main", vcMain, reporter);
- checker.ProverDone.WaitOne();
-
- ProverInterface.Outcome outcome = (checker).ReadOutcome();
- numQueries++;
-
- switch (outcome)
- {
- case ProverInterface.Outcome.Valid:
- return Outcome.Correct;
- case ProverInterface.Outcome.Invalid:
- return Outcome.Errors;
- case ProverInterface.Outcome.OutOfMemory:
- return Outcome.OutOfMemory;
- case ProverInterface.Outcome.TimeOut:
- return Outcome.TimedOut;
- case ProverInterface.Outcome.Undetermined:
- return Outcome.Inconclusive;
- default:
- Contract.Assert(false);
- throw new cce.UnreachableException();
- }
-
- }
-
- public override void Push()
- {
- numAxiomsPushed.Add(0);
- }
-
- public override void Pop()
- {
- Debug.Assert(numAxiomsPushed.Count > 0);
- checker.TheoremProver.FlushAxiomsToTheoremProver();
- var n = numAxiomsPushed.Last();
- numAxiomsPushed.RemoveAt(numAxiomsPushed.Count - 1);
-
- for (int i = 0; i < n; i++)
- {
- checker.TheoremProver.Pop();
- }
- }
-
- public override void AddAxiom(VCExpr vc)
- {
- Debug.Assert(numAxiomsPushed.Count > 0);
- int oldnum = checker.TheoremProver.NumAxiomsPushed();
-
- checker.TheoremProver.PushVCExpression(vc);
-
- int newnum = checker.TheoremProver.NumAxiomsPushed();
- numAxiomsPushed[numAxiomsPushed.Count - 1] += (newnum - oldnum);
- }
-
- public override void LogComment(string str)
- {
- checker.TheoremProver.LogComment(str);
- }
-
- }
-
-
- public class ApiChecker : StratifiedCheckerInterface {
+ public class ApiChecker {
// The VC of main
private VCExpr vcMain;
// Error reporter (stores models)
@@ -1174,34 +1038,40 @@ namespace VC
// stores the number of axioms pushed since pervious backtracking point
private List<int> numAxiomsPushed;
// Api-based theorem prover
- private ApiProverInterface TheoremProver;
+ private ProverInterface TheoremProver;
// Use checkAssumptions?
public static bool UseCheckAssumptions = true;
+ private FCallHandler calls;
+ // Underlying checker
+ public Checker underlyingChecker;
+ // Statistics
+ public int numQueries;
- public ApiChecker(VCExpr vcMain, ProverInterface.ErrorHandler reporter, Checker checker) {
+ public ApiChecker(VCExpr vcMain, ProverInterface.ErrorHandler reporter, Checker checker, FCallHandler calls) {
this.vcMain = vcMain;
this.reporter = reporter;
this.checker = checker;
this.underlyingChecker = checker;
+ this.calls = calls;
numAxiomsPushed = new List<int>();
numQueries = 0;
- TheoremProver = checker.TheoremProver as ApiProverInterface;
+ TheoremProver = checker.TheoremProver;
Debug.Assert(TheoremProver != null);
// Add main to the TP stack
TheoremProver.Assert(vcMain, false);
}
- public override void updateMainVC(VCExpr vcMain) {
+ public void updateMainVC(VCExpr vcMain) {
throw new NotImplementedException("Stratified non-incremental search is not yet supported with z3api");
}
- public override Outcome CheckVC() {
+ public Outcome CheckVC() {
Contract.EnsuresOnThrow<UnexpectedProverOutputException>(true);
TheoremProver.AssertAxioms();
TheoremProver.Check();
- ProverInterface.Outcome outcome = TheoremProver.CheckOutcome(reporter);
+ ProverInterface.Outcome outcome = TheoremProver.CheckOutcomeCore(reporter);
numQueries++;
switch (outcome) {
@@ -1221,26 +1091,48 @@ namespace VC
}
}
- public override void Push() {
+ public void Push() {
TheoremProver.Push();
}
- public override void Pop() {
+ public void Pop() {
TheoremProver.AssertAxioms();
TheoremProver.Pop();
}
- public override void AddAxiom(VCExpr vc) {
+ public void AddAxiom(VCExpr vc) {
TheoremProver.Assert(vc, true);
}
- public override void LogComment(string str) {
+ public void LogComment(string str) {
checker.TheoremProver.LogComment(str);
}
- public override Outcome CheckAssumptions(List<VCExpr> assumptions, out List<int> unsatCore) {
+ public Outcome CheckAssumptions(List<VCExpr> assumptions, out List<int> unsatCore) {
if (!UseCheckAssumptions) {
- return base.CheckAssumptions(assumptions, out unsatCore);
+ Outcome ret;
+
+ unsatCore = new List<int>();
+ for (int i = 0; i < assumptions.Count; i++)
+ unsatCore.Add(i);
+
+ if (assumptions.Count == 0)
+ {
+ return CheckVC();
+ }
+
+ Push();
+
+ foreach (var a in assumptions)
+ {
+ AddAxiom(a);
+ }
+ ret = CheckVC();
+
+ Pop();
+
+ return ret;
+
}
if (assumptions.Count == 0) {
@@ -1248,11 +1140,11 @@ namespace VC
return CheckVC();
}
- //TheoremProver.Push();
+ TheoremProver.Push();
TheoremProver.AssertAxioms();
TheoremProver.CheckAssumptions(assumptions, out unsatCore);
- ProverInterface.Outcome outcome = TheoremProver.CheckOutcome(reporter);
- //TheoremProver.Pop();
+ ProverInterface.Outcome outcome = TheoremProver.CheckOutcomeCore(reporter);
+ TheoremProver.Pop();
numQueries++;
switch (outcome) {
@@ -1272,7 +1164,7 @@ namespace VC
}
}
- public override void SetTimeOut(int msec)
+ public void SetTimeOut(int msec)
{
TheoremProver.SetTimeOut(msec);
}
@@ -1289,7 +1181,7 @@ namespace VC
public ProverInterface.ErrorHandler reporter;
// The theorem prover interface
//public Checker checker;
- public StratifiedCheckerInterface checker;
+ public ApiChecker checker;
// The coverage graph reporter
public CoverageGraphManager coverageManager;
// For statistics
@@ -1303,7 +1195,7 @@ namespace VC
}
}
// For making summary queries on the side
- public StratifiedCheckerInterface checker2;
+ public ApiChecker checker2;
public VerificationState(VCExpr vcMain, FCallHandler calls,
ProverInterface.ErrorHandler reporter, Checker checker, Checker checker2)
@@ -1311,18 +1203,10 @@ namespace VC
this.vcMain = vcMain;
this.calls = calls;
this.reporter = reporter;
- if (checker.TheoremProver is ApiProverInterface)
- {
- this.checker = new ApiChecker(vcMain, reporter , checker);
- if(checker2 != null)
- this.checker2 = new ApiChecker(VCExpressionGenerator.False, new EmptyErrorHandler(), checker2);
- }
- else
- {
- this.checker = new NormalChecker(vcMain, reporter, checker);
+
+ this.checker = new ApiChecker(vcMain, reporter, checker, calls);
if(checker2 != null)
- this.checker2 = new NormalChecker(VCExpressionGenerator.False, new EmptyErrorHandler(), checker2);
- }
+ this.checker2 = new ApiChecker(VCExpressionGenerator.False, new EmptyErrorHandler(), checker2, calls);
vcSize = 0;
expansionCount = 0;
@@ -1369,7 +1253,14 @@ namespace VC
ConvertCFG2DAG(impl, program);
Hashtable/*TransferCmd->ReturnCmd*/ gotoCmdOrigins = PassifyImpl(impl, program, out mvInfo);
- vcMain = GenerateVC(impl, null, out mainLabel2absy, checker);
+ var exprGen = checker.TheoremProver.Context.ExprGen;
+ VCExpr controlFlowVariableExpr = CommandLineOptions.Clo.UseLabels ? null : exprGen.Integer(BigNum.ZERO);
+ vcMain = GenerateVC(impl, controlFlowVariableExpr, out mainLabel2absy, checker);
+ if (!CommandLineOptions.Clo.UseLabels) {
+ VCExpr controlFlowFunctionAppl = exprGen.ControlFlowFunctionApplication(exprGen.Integer(BigNum.ZERO), exprGen.Integer(BigNum.ZERO));
+ VCExpr eqExpr = exprGen.Eq(controlFlowFunctionAppl, exprGen.Integer(BigNum.FromInt(impl.Blocks[0].UniqueId)));
+ vcMain = exprGen.Implies(eqExpr, vcMain);
+ }
// Find all procedure calls in vc and put labels on them
FCallHandler calls = new FCallHandler(checker.VCExprGen, implName2StratifiedInliningInfo, impl.Name, mainLabel2absy);
@@ -1424,7 +1315,7 @@ namespace VC
return Outcome.Correct;
}
- private HashSet<VCExprVar> refinementLoop(StratifiedCheckerInterface apiChecker, HashSet<VCExprVar> trackedVars, HashSet<VCExprVar> trackedVarsUpperBound, HashSet<VCExprVar> allVars)
+ private HashSet<VCExprVar> refinementLoop(ApiChecker apiChecker, HashSet<VCExprVar> trackedVars, HashSet<VCExprVar> trackedVarsUpperBound, HashSet<VCExprVar> allVars)
{
Debug.Assert(trackedVars.IsSubsetOf(trackedVarsUpperBound));
@@ -1466,7 +1357,7 @@ namespace VC
Dictionary<int, List<HashSet<string>>> satQueryCache;
Dictionary<int, List<HashSet<string>>> unsatQueryCache;
- private bool refinementLoopCheckPath(StratifiedCheckerInterface apiChecker, HashSet<VCExprVar> varsToSet, HashSet<VCExprVar> allVars)
+ private bool refinementLoopCheckPath(ApiChecker apiChecker, HashSet<VCExprVar> varsToSet, HashSet<VCExprVar> allVars)
{
var assumptions = new List<VCExpr>();
List<int> temp = null;
@@ -1635,9 +1526,6 @@ namespace VC
Hashtable/*<int, Absy!>*/ mainLabel2absy;
GetVC(impl, program, callback, out vc, out mainLabel2absy, out reporter);
- if (CommandLineOptions.Clo.ProcedureCopyBound > 0) {
- return SuperAwesomeMethod(checker, impl, vc);
- }
// Find all procedure calls in vc and put labels on them
FCallHandler calls = new FCallHandler(checker.VCExprGen, implName2StratifiedInliningInfo, impl.Name, mainLabel2absy);
@@ -1706,9 +1594,9 @@ namespace VC
#endregion
#region Coverage reporter
- if (CommandLineOptions.Clo.CoverageReporterPath == "Console")
+ if (CommandLineOptions.Clo.StratifiedInliningVerbose > 0)
{
- Console.WriteLine("Stratified Inlining: Size of VC after eager inlining: {0}", vState.vcSize);
+ Console.WriteLine(">> SI: Size of VC after eager inlining: {0}", vState.vcSize);
}
#endregion
@@ -1896,13 +1784,13 @@ namespace VC
vState.checker.Pop();
#region Coverage reporter
- if (CommandLineOptions.Clo.CoverageReporterPath == "Console")
+ if (CommandLineOptions.Clo.StratifiedInliningVerbose > 0)
{
- Console.WriteLine("Stratified Inlining: Calls to Z3: {0}", vState.numQueries);
- Console.WriteLine("Stratified Inlining: Expansions performed: {0}", vState.expansionCount);
- Console.WriteLine("Stratified Inlining: Candidates left: {0}", calls.currCandidates.Count);
- Console.WriteLine("Stratified Inlining: Nontrivial Candidates left: {0}", calls.numNonTrivialCandidates());
- Console.WriteLine("Stratified Inlining: VC Size: {0}", vState.vcSize);
+ Console.WriteLine(">> SI: Calls to Z3: {0}", vState.numQueries);
+ Console.WriteLine(">> SI: Expansions performed: {0}", vState.expansionCount);
+ Console.WriteLine(">> SI: Candidates left: {0}", calls.currCandidates.Count);
+ Console.WriteLine(">> SI: Nontrivial Candidates left: {0}", calls.numNonTrivialCandidates());
+ Console.WriteLine(">> SI: VC Size: {0}", vState.vcSize);
}
#endregion
coverageManager.stop();
@@ -1963,7 +1851,8 @@ namespace VC
} // end PCBInliner
- private void InlineCallSite(CallSite cs, StratifiedCheckerInterface checker) {
+ private void InlineCallSite(CallSite cs, ApiChecker checker)
+ {
var Gen = checker.underlyingChecker.VCExprGen;
var callee = cs.calleeName;
var caller = cs.callerName;
@@ -2023,7 +1912,8 @@ namespace VC
calleeToCallSites[callee].Remove(cs);
}
- private Outcome FindUnsatCoreInMainCallees(Implementation impl, StratifiedCheckerInterface checker, VCExpressionGenerator Gen, PCBErrorReporter reporter, List<VCExpr> assumptions, out HashSet<VCExprVar> unsatCore) {
+ private Outcome FindUnsatCoreInMainCallees(Implementation impl, ApiChecker checker, VCExpressionGenerator Gen, PCBErrorReporter reporter, List<VCExpr> assumptions, out HashSet<VCExprVar> unsatCore)
+ {
Debug.Assert(checker is ApiChecker);
unsatCore = null;
List<int> unsatCoreIndices;
@@ -2044,7 +1934,8 @@ namespace VC
return Outcome.Correct;
}
- private Outcome FindUnsatCore(Implementation impl, StratifiedCheckerInterface checker, VCExpressionGenerator Gen, PCBErrorReporter reporter, List<VCExpr> assumptions, out HashSet<VCExprVar> unsatCore) {
+ private Outcome FindUnsatCore(Implementation impl, ApiChecker checker, VCExpressionGenerator Gen, PCBErrorReporter reporter, List<VCExpr> assumptions, out HashSet<VCExprVar> unsatCore)
+ {
Helpers.ExtraTraceInformation("Number of assumptions = " + assumptions.Count);
unsatCore = null;
List<int> unsatCoreIndices;
@@ -2175,7 +2066,8 @@ namespace VC
return verified;
}
- private void InlineBottomUp(StratifiedCheckerInterface checker, HashSet<VCExprVar> unsatCore) {
+ private void InlineBottomUp(ApiChecker checker, HashSet<VCExprVar> unsatCore)
+ {
Graph<string> callGraph = new Graph<string>();
foreach (string name in calleeToCallSites.Keys) {
callGraph.AddSource(name);
@@ -2197,7 +2089,8 @@ namespace VC
}
}
- private void InlineIntoMain(StratifiedCheckerInterface checker, Implementation impl, HashSet<VCExprVar> unsatCore) {
+ private void InlineIntoMain(ApiChecker checker, Implementation impl, HashSet<VCExprVar> unsatCore)
+ {
HashSet<CallSite> toBeInlined = new HashSet<CallSite>();
foreach (CallSite cs in callerToCallSites[impl.Name]) {
if (unsatCore.Contains(cs.callSiteConstant)) {
@@ -2220,8 +2113,8 @@ namespace VC
var Gen = underlyingChecker.VCExprGen;
PCBErrorReporter reporter = new PCBErrorReporter(impl);
- StratifiedCheckerInterface checker;
- checker = new ApiChecker(VCExpressionGenerator.False, reporter, underlyingChecker);
+ ApiChecker checker;
+ checker = new ApiChecker(VCExpressionGenerator.False, reporter, underlyingChecker, null);
CreateProcedureCopies(impl, program, checker, vcMain);
int iter = 0;
@@ -2460,6 +2353,14 @@ namespace VC
}
//Console.WriteLine("Inlining {0}", procName);
VCExpr expansion = cce.NonNull(info.vcexpr);
+
+ if (!CommandLineOptions.Clo.UseLabels) {
+ var ctx = checker.TheoremProver.Context;
+ var bet = ctx.BoogieExprTranslator;
+ VCExpr controlFlowVariableExpr = bet.LookupVariable(info.controlFlowVariable);
+ VCExpr eqExpr = ctx.ExprGen.Eq(controlFlowVariableExpr, ctx.ExprGen.Integer(BigNum.FromInt(id)));
+ expansion = ctx.ExprGen.And(eqExpr, expansion);
+ }
// Instantiate the "forall" variables
Dictionary<VCExprVar, VCExpr> substForallDict = new Dictionary<VCExprVar, VCExpr>();
@@ -2629,8 +2530,17 @@ namespace VC
Hashtable/*TransferCmd->ReturnCmd*/ gotoCmdOrigins = PassifyImpl(impl, program, out mvInfo);
Checker checker = FindCheckerFor(impl, CommandLineOptions.Clo.ProverKillTime);
Contract.Assert(checker != null);
-
- vc = GenerateVC(impl, null, out label2absy, checker);
+
+ var exprGen = checker.TheoremProver.Context.ExprGen;
+ VCExpr controlFlowVariableExpr = CommandLineOptions.Clo.UseLabels ? null : exprGen.Integer(BigNum.ZERO);
+
+ vc = GenerateVC(impl, controlFlowVariableExpr, out label2absy, checker);
+
+ if (!CommandLineOptions.Clo.UseLabels) {
+ VCExpr controlFlowFunctionAppl = exprGen.ControlFlowFunctionApplication(exprGen.Integer(BigNum.ZERO), exprGen.Integer(BigNum.ZERO));
+ VCExpr eqExpr = exprGen.Eq(controlFlowFunctionAppl, exprGen.Integer(BigNum.FromInt(impl.Blocks[0].UniqueId)));
+ vc = exprGen.Implies(eqExpr, vc);
+ }
reporter = new StratifiedInliningErrorReporter(
cce.NonNull(implName2StratifiedInliningInfo), checker.TheoremProver, callback, mvInfo,
@@ -3159,6 +3069,10 @@ namespace VC
summaryTemp.Clear();
}
+ public IEnumerable<int> getInlinedCandidates() {
+ return candidateParent.Keys.Except(currCandidates).Union(new int[] { 0 });
+ }
+
} // end FCallHandler
// Collects the set of all VCExprVar in a given VCExpr
@@ -3435,9 +3349,131 @@ namespace VC
return;
}
- public override void OnModel(IList<string/*!*/>/*!*/ labels, ErrorModel errModel)
+ public override void OnModel(IList<string> labels, ErrorModel errModel) {
+ if (CommandLineOptions.Clo.UseLabels)
+ OnModelOld(labels, errModel);
+ else
+ OnModelNew(labels, errModel);
+ }
+
+ private void OnModelNew(IList<string> labels, ErrorModel errModel) {
+ List<Absy> absyList = new List<Absy>();
+ foreach (var label in labels) {
+ absyList.Add(Label2Absy(label));
+ }
+
+ orderedStateIds = new List<Tuple<int, int>>();
+ candidatesToExpand = new List<int>();
+
+ Model model = null;
+ if (errModel != null) model = errModel.ToModel();
+
+ if (underapproximationMode) {
+ var cex = NewTrace(0, absyList, model);
+ Debug.Assert(candidatesToExpand.Count == 0);
+ if (cex != null) {
+ GetModelWithStates(model);
+ callback.OnCounterexample(cex, null);
+ this.PrintModel(model);
+ }
+ return;
+ }
+
+ NewTrace(0, absyList, model);
+ }
+
+ private Counterexample NewTrace(int candidateId, List<Absy> absyList, Model model) {
+ AssertCmd assertCmd = (AssertCmd)absyList[absyList.Count - 1];
+ BlockSeq trace = new BlockSeq();
+ var calleeCounterexamples = new Dictionary<TraceLocation, CalleeCounterexampleInfo>();
+ for (int j = 0; j < absyList.Count - 1; j++) {
+ Block b = (Block)absyList[j];
+ trace.Add(b);
+ CmdSeq cmdSeq = b.Cmds;
+ for (int i = 0; i < cmdSeq.Length; i++) {
+ Cmd cmd = cmdSeq[i];
+ if (cmd == assertCmd) break;
+ AssumeCmd assumeCmd = cmd as AssumeCmd;
+ if (assumeCmd == null) continue;
+ NAryExpr naryExpr = assumeCmd.Expr as NAryExpr;
+ if (naryExpr == null)
+ continue;
+ string calleeName = naryExpr.Fun.FunctionName;
+ Contract.Assert(calleeName != null);
+
+ BinaryOperator binOp = naryExpr.Fun as BinaryOperator;
+ if (binOp != null && binOp.Op == BinaryOperator.Opcode.And) {
+ Expr expr = naryExpr.Args[0];
+ NAryExpr mvStateExpr = expr as NAryExpr;
+ if (mvStateExpr != null && mvStateExpr.Fun.FunctionName == ModelViewInfo.MVState_FunctionDef.Name) {
+ LiteralExpr x = mvStateExpr.Args[1] as LiteralExpr;
+ orderedStateIds.Add(new Tuple<int, int>(candidateId, x.asBigNum.ToInt));
+ }
+ }
+
+ if (calleeName.StartsWith(recordProcName) && model != null) {
+ var expr = calls.recordExpr2Var[new BoogieCallExpr(naryExpr, candidateId)];
+
+ // Record concrete value of the argument to this procedure
+ var args = new List<Model.Element>();
+ if (expr is VCExprIntLit) {
+ args.Add(model.MkElement((expr as VCExprIntLit).Val.ToString()));
+ }
+ else if (expr == VCExpressionGenerator.True) {
+ args.Add(model.MkElement("true"));
+ }
+ else if (expr == VCExpressionGenerator.False) {
+ args.Add(model.MkElement("false"));
+ }
+ else if (expr is VCExprVar) {
+ var idExpr = expr as VCExprVar;
+ string name = context.Lookup(idExpr);
+ Contract.Assert(name != null);
+ Model.Func f = model.TryGetFunc(name);
+ if (f != null) {
+ args.Add(f.GetConstant());
+ }
+ }
+ else {
+ Contract.Assert(false);
+ }
+ calleeCounterexamples[new TraceLocation(trace.Length - 1, i)] =
+ new CalleeCounterexampleInfo(null, args);
+ continue;
+ }
+
+ if (!implName2StratifiedInliningInfo.ContainsKey(calleeName))
+ continue;
+
+ int calleeId = calls.boogieExpr2Id[new BoogieCallExpr(naryExpr, candidateId)];
+
+ if (calls.currCandidates.Contains(calleeId)) {
+ candidatesToExpand.Add(calleeId);
+ }
+ else {
+ orderedStateIds.Add(new Tuple<int, int>(calleeId, StratifiedInliningErrorReporter.CALL));
+ string[] labels = theoremProver.CalculatePath(calleeId);
+ List<Absy> calleeAbsyList = new List<Absy>();
+ foreach (string label in labels) {
+ VCExprNAry expr = calls.id2Candidate[calleeId];
+ string procName = (cce.NonNull(expr.Op as VCExprBoogieFunctionOp)).Func.Name;
+ calleeAbsyList.Add(Label2Absy(procName, label));
+ }
+ calleeCounterexamples[new TraceLocation(trace.Length - 1, i)] =
+ new CalleeCounterexampleInfo(NewTrace(calleeId, calleeAbsyList, model), new List<Model.Element>());
+ orderedStateIds.Add(new Tuple<int, int>(candidateId, StratifiedInliningErrorReporter.RETURN));
+ }
+ }
+ }
+
+ Block lastBlock = (Block)absyList[absyList.Count - 2];
+ Counterexample newCounterexample = AssertCmdToCounterexample(assertCmd, lastBlock.TransferCmd, trace, model, mvInfo, context);
+ newCounterexample.AddCalleeCounterexample(calleeCounterexamples);
+ return newCounterexample;
+ }
+
+ public void OnModelOld(IList<string/*!*/>/*!*/ labels, ErrorModel errModel)
{
- //if (procBoundingMode) return; // shaz hack
Contract.Assert(CommandLineOptions.Clo.StratifiedInliningWithoutModels || errModel != null);
candidatesToExpand = new List<int>();
@@ -3445,7 +3481,6 @@ namespace VC
Model model = null;
if (errModel != null) model = errModel.ToModel();
- //Contract.Requires(cce.NonNullElements(labels));
if (underapproximationMode)
{
var cex = GenerateTraceMain(labels, model, mvInfo);
@@ -3475,7 +3510,7 @@ namespace VC
orderedStateIds = new List<Tuple<int,int>>();
Counterexample newCounterexample =
- GenerateTrace(labels, errModel, mvInfo, 0, orderedStateIds, mainImpl);
+ GenerateTrace(labels, errModel, 0, mainImpl);
if (newCounterexample == null)
return null;
@@ -3501,8 +3536,8 @@ namespace VC
return newCounterexample;
}
- private Counterexample GenerateTrace(IList<string/*!*/>/*!*/ labels, Model/*!*/ errModel, ModelViewInfo mvInfo,
- int candidateId, List<Tuple<int,int>> orderedStateIds, Implementation procImpl)
+ private Counterexample GenerateTrace(IList<string/*!*/>/*!*/ labels, Model/*!*/ errModel,
+ int candidateId, Implementation procImpl)
{
Contract.Requires(cce.NonNullElements(labels));
Contract.Requires(procImpl != null);
@@ -3542,14 +3577,14 @@ namespace VC
trace.Add(entryBlock);
var calleeCounterexamples = new Dictionary<TraceLocation, CalleeCounterexampleInfo>();
- Counterexample newCounterexample = GenerateTraceRec(labels, errModel, mvInfo, candidateId, orderedStateIds, entryBlock, traceNodes, trace, calleeCounterexamples);
+ Counterexample newCounterexample = GenerateTraceRec(labels, errModel, mvInfo, candidateId, entryBlock, traceNodes, trace, calleeCounterexamples);
return newCounterexample;
}
private Counterexample GenerateTraceRec(
IList<string/*!*/>/*!*/ labels, Model/*!*/ errModel, ModelViewInfo mvInfo,
- int candidateId, List<Tuple<int,int>> orderedStateIds,
+ int candidateId,
Block/*!*/ b, Hashtable/*!*/ traceNodes, BlockSeq/*!*/ trace,
Dictionary<TraceLocation/*!*/, CalleeCounterexampleInfo/*!*/>/*!*/ calleeCounterexamples)
{
@@ -3570,7 +3605,7 @@ namespace VC
// Skip if 'cmd' not contained in the trace or not an assert
if (cmd is AssertCmd && traceNodes.Contains(cmd))
{
- Counterexample newCounterexample = AssertCmdToCounterexample((AssertCmd)cmd, transferCmd, trace, errModel, mvInfo, context, new Dictionary<Incarnation, Absy/*!*/>());
+ Counterexample newCounterexample = AssertCmdToCounterexample((AssertCmd)cmd, transferCmd, trace, errModel, mvInfo, context);
newCounterexample.AddCalleeCounterexample(calleeCounterexamples);
return newCounterexample;
}
@@ -3591,9 +3626,7 @@ namespace VC
NAryExpr mvStateExpr = expr as NAryExpr;
if (mvStateExpr != null && mvStateExpr.Fun.FunctionName == ModelViewInfo.MVState_FunctionDef.Name) {
LiteralExpr x = mvStateExpr.Args[1] as LiteralExpr;
- Debug.Assert(x != null);
- int foo = x.asBigNum.ToInt;
- orderedStateIds.Add(new Tuple<int, int>(candidateId, foo));
+ orderedStateIds.Add(new Tuple<int, int>(candidateId, x.asBigNum.ToInt));
}
}
@@ -3652,7 +3685,7 @@ namespace VC
orderedStateIds.Add(new Tuple<int, int>(actualId, StratifiedInliningErrorReporter.CALL));
calleeCounterexamples[new TraceLocation(trace.Length - 1, i)] =
new CalleeCounterexampleInfo(
- cce.NonNull(GenerateTrace(labels, errModel, mvInfo, actualId, orderedStateIds, implName2StratifiedInliningInfo[calleeName].impl)),
+ cce.NonNull(GenerateTrace(labels, errModel, actualId, implName2StratifiedInliningInfo[calleeName].impl)),
new List<Model.Element>());
orderedStateIds.Add(new Tuple<int, int>(candidateId, StratifiedInliningErrorReporter.RETURN));
}
@@ -3670,7 +3703,7 @@ namespace VC
orderedStateIds.Add(new Tuple<int, int>(actualId, StratifiedInliningErrorReporter.CALL));
calleeCounterexamples[new TraceLocation(trace.Length - 1, i)] =
new CalleeCounterexampleInfo(
- cce.NonNull(GenerateTrace(labels, errModel, mvInfo, actualId, orderedStateIds, implName2StratifiedInliningInfo[calleeName].impl)),
+ cce.NonNull(GenerateTrace(labels, errModel, actualId, implName2StratifiedInliningInfo[calleeName].impl)),
new List<Model.Element>());
orderedStateIds.Add(new Tuple<int, int>(candidateId, StratifiedInliningErrorReporter.RETURN));
}
@@ -3682,7 +3715,7 @@ namespace VC
orderedStateIds.Add(new Tuple<int, int>(calleeId, StratifiedInliningErrorReporter.CALL));
calleeCounterexamples[new TraceLocation(trace.Length - 1, i)] =
new CalleeCounterexampleInfo(
- cce.NonNull(GenerateTrace(labels, errModel, mvInfo, calleeId, orderedStateIds, implName2StratifiedInliningInfo[calleeName].impl)),
+ cce.NonNull(GenerateTrace(labels, errModel, calleeId, implName2StratifiedInliningInfo[calleeName].impl)),
new List<Model.Element>());
orderedStateIds.Add(new Tuple<int, int>(candidateId, StratifiedInliningErrorReporter.RETURN));
}
diff --git a/Source/VCGeneration/VC.cs b/Source/VCGeneration/VC.cs
index 49fa7144..008810cb 100644
--- a/Source/VCGeneration/VC.cs
+++ b/Source/VCGeneration/VC.cs
@@ -102,7 +102,7 @@ namespace VC {
this.impl = impl;
this.uniqueId = uniqueId;
- this.controlFlowVariable = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, "cfc", Microsoft.Boogie.Type.Int));
+ this.controlFlowVariable = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, "@cfc", Microsoft.Boogie.Type.Int));
impl.LocVars.Add(controlFlowVariable);
List<Variable> interfaceVars = new List<Variable>();
@@ -272,7 +272,7 @@ namespace VC {
TypecheckingContext tc = new TypecheckingContext(null);
impl.Typecheck(tc);
int assertionCount;
- VCExpr vcexpr = gen.Not(LetVC(impl.Blocks[0], info.controlFlowVariable, null, checker.TheoremProver.Context, out assertionCount));
+ VCExpr vcexpr = gen.Not(LetVC(impl.Blocks[0], translator.LookupVariable(info.controlFlowVariable), null, checker.TheoremProver.Context, out assertionCount));
CumulativeAssertionCount += assertionCount;
Contract.Assert(vcexpr != null);
ResetPredecessors(impl.Blocks);
@@ -607,8 +607,19 @@ namespace VC {
Hashtable label2Absy;
Checker ch = parent.FindCheckerFor(impl, CommandLineOptions.Clo.SmokeTimeout);
Contract.Assert(ch != null);
- VCExpr vc = parent.GenerateVC(impl, null, out label2Absy, ch);
+
+ var exprGen = ch.TheoremProver.Context.ExprGen;
+ VCExpr controlFlowVariableExpr = CommandLineOptions.Clo.UseLabels ? null : exprGen.Integer(BigNum.ZERO);
+
+ VCExpr vc = parent.GenerateVC(impl, controlFlowVariableExpr, out label2Absy, ch);
Contract.Assert(vc != null);
+
+ if (!CommandLineOptions.Clo.UseLabels) {
+ VCExpr controlFlowFunctionAppl = exprGen.ControlFlowFunctionApplication(exprGen.Integer(BigNum.ZERO), exprGen.Integer(BigNum.ZERO));
+ VCExpr eqExpr = exprGen.Eq(controlFlowFunctionAppl, exprGen.Integer(BigNum.FromInt(impl.Blocks[0].UniqueId)));
+ vc = exprGen.Implies(eqExpr, vc);
+ }
+
impl.Blocks = backup;
if (CommandLineOptions.Clo.TraceVerify) {
@@ -1329,7 +1340,7 @@ namespace VC {
foreach (Cmd c in b.Cmds) {
Contract.Assert(c != null);
if (c is AssertCmd) {
- return AssertCmdToCounterexample((AssertCmd)c, cce.NonNull(b.TransferCmd), trace, null, null, context, new Dictionary<Incarnation, Absy>());
+ return AssertCmdToCounterexample((AssertCmd)c, cce.NonNull(b.TransferCmd), trace, null, null, context);
}
}
}
@@ -1536,22 +1547,16 @@ namespace VC {
}
));
- LocalVariable controlFlowVariable = null;
+ var exprGen = ctx.ExprGen;
+ VCExpr controlFlowVariableExpr = CommandLineOptions.Clo.UseLabels ? null : exprGen.Integer(BigNum.ZERO);
- if (!CommandLineOptions.Clo.UseLabels) {
- controlFlowVariable = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, "@cfc", Microsoft.Boogie.Type.Int));
- impl.LocVars.Add(controlFlowVariable);
- }
-
- VCExpr vc = parent.GenerateVCAux(impl, controlFlowVariable, label2absy, checker);
+ VCExpr vc = parent.GenerateVCAux(impl, controlFlowVariableExpr, label2absy, checker);
Contract.Assert(vc != null);
if (!CommandLineOptions.Clo.UseLabels) {
- VCExpr controlFlowVariableExpr = bet.LookupVariable(controlFlowVariable);
- Contract.Assert(controlFlowVariableExpr != null);
- VCExpr controlFlowFunctionAppl = ctx.ExprGen.ControlFlowFunctionApplication(controlFlowVariableExpr, ctx.ExprGen.Integer(BigNum.ZERO));
- Contract.Assert(controlFlowFunctionAppl != null);
- vc = ctx.ExprGen.Implies(ctx.ExprGen.Eq(controlFlowFunctionAppl, ctx.ExprGen.Integer(BigNum.FromInt(impl.Blocks[0].UniqueId))), vc);
+ VCExpr controlFlowFunctionAppl = exprGen.ControlFlowFunctionApplication(exprGen.Integer(BigNum.ZERO), exprGen.Integer(BigNum.ZERO));
+ VCExpr eqExpr = exprGen.Eq(controlFlowFunctionAppl, exprGen.Integer(BigNum.FromInt(impl.Blocks[0].UniqueId)));
+ vc = exprGen.Implies(eqExpr, vc);
}
if (CommandLineOptions.Clo.vcVariety == CommandLineOptions.VCVariety.Local) {
@@ -1625,7 +1630,7 @@ namespace VC {
}
#endregion
- public VCExpr GenerateVC(Implementation/*!*/ impl, Variable controlFlowVariable, out Hashtable/*<int, Absy!>*//*!*/ label2absy, Checker/*!*/ ch)
+ public VCExpr GenerateVC(Implementation/*!*/ impl, VCExpr controlFlowVariableExpr, out Hashtable/*<int, Absy!>*//*!*/ label2absy, Checker/*!*/ ch)
{
Contract.Requires(impl != null);
Contract.Requires(ch != null);
@@ -1633,10 +1638,10 @@ namespace VC {
Contract.Ensures(Contract.Result<VCExpr>() != null);
label2absy = new Hashtable/*<int, Absy!>*/();
- return GenerateVCAux(impl, controlFlowVariable, label2absy, ch);
+ return GenerateVCAux(impl, controlFlowVariableExpr, label2absy, ch);
}
- protected VCExpr GenerateVCAux(Implementation/*!*/ impl, Variable controlFlowVariable, Hashtable/*<int, Absy!>*//*!*/ label2absy, Checker/*!*/ ch) {
+ protected VCExpr GenerateVCAux(Implementation/*!*/ impl, VCExpr controlFlowVariableExpr, Hashtable/*<int, Absy!>*//*!*/ label2absy, Checker/*!*/ ch) {
Contract.Requires(impl != null);
Contract.Requires(ch != null);
Contract.Ensures(Contract.Result<VCExpr>() != null);
@@ -1667,13 +1672,13 @@ namespace VC {
break;
case CommandLineOptions.VCVariety.Dag:
if (cce.NonNull(CommandLineOptions.Clo.TheProverFactory).SupportsDags) {
- vc = DagVC(cce.NonNull(impl.Blocks[0]), label2absy, new Hashtable/*<Block, VCExpr!>*/(), ch.TheoremProver.Context, out assertionCount);
+ vc = DagVC(cce.NonNull(impl.Blocks[0]), controlFlowVariableExpr, label2absy, new Hashtable/*<Block, VCExpr!>*/(), ch.TheoremProver.Context, out assertionCount);
} else {
- vc = LetVC(cce.NonNull(impl.Blocks[0]), controlFlowVariable, label2absy, ch.TheoremProver.Context, out assertionCount);
+ vc = LetVC(cce.NonNull(impl.Blocks[0]), controlFlowVariableExpr, label2absy, ch.TheoremProver.Context, out assertionCount);
}
break;
case CommandLineOptions.VCVariety.DagIterative:
- vc = LetVCIterative(impl.Blocks, controlFlowVariable, label2absy, ch.TheoremProver.Context, out assertionCount);
+ vc = LetVCIterative(impl.Blocks, controlFlowVariableExpr, label2absy, ch.TheoremProver.Context, out assertionCount);
break;
case CommandLineOptions.VCVariety.Doomed:
vc = FlatBlockVC(impl, label2absy, false, false, true, ch.TheoremProver.Context, out assertionCount);
@@ -2065,7 +2070,7 @@ namespace VC {
if (b.Cmds.Has(a)) {
BlockSeq trace = new BlockSeq();
trace.Add(b);
- Counterexample newCounterexample = AssertCmdToCounterexample(a, cce.NonNull(b.TransferCmd), trace, errModel == null ? null : errModel.ToModel(), MvInfo, context, incarnationOriginMap);
+ Counterexample newCounterexample = AssertCmdToCounterexample(a, cce.NonNull(b.TransferCmd), trace, errModel == null ? null : errModel.ToModel(), MvInfo, context);
callback.OnCounterexample(newCounterexample, null);
goto NEXT_ASSERT;
}
@@ -2716,7 +2721,7 @@ namespace VC {
if (assertCmd != null && controlFlowFunction.TryEval(cfcValue, errModel.MkIntElement(b.UniqueId)).AsInt() == assertCmd.UniqueId)
{
Counterexample newCounterexample;
- newCounterexample = AssertCmdToCounterexample(assertCmd, transferCmd, trace, errModel, mvInfo, context, cce.NonNull(info.incarnationOriginMap));
+ newCounterexample = AssertCmdToCounterexample(assertCmd, transferCmd, trace, errModel, mvInfo, context);
newCounterexample.AddCalleeCounterexample(calleeCounterexamples);
return newCounterexample;
}
@@ -2854,7 +2859,7 @@ namespace VC {
// Skip if 'cmd' not contained in the trace or not an assert
if (cmd is AssertCmd && traceNodes.Contains(cmd))
{
- Counterexample newCounterexample = AssertCmdToCounterexample((AssertCmd)cmd, transferCmd, trace, errModel, mvInfo, context, incarnationOriginMap);
+ Counterexample newCounterexample = AssertCmdToCounterexample((AssertCmd)cmd, transferCmd, trace, errModel, mvInfo, context);
Contract.Assert(newCounterexample != null);
newCounterexample.AddCalleeCounterexample(calleeCounterexamples);
return newCounterexample;
@@ -3399,14 +3404,12 @@ namespace VC {
}
}
- protected static Counterexample AssertCmdToCounterexample(AssertCmd cmd, TransferCmd transferCmd, BlockSeq trace, Model errModel, ModelViewInfo mvInfo, ProverContext context,
- Dictionary<Incarnation, Absy> incarnationOriginMap)
+ protected static Counterexample AssertCmdToCounterexample(AssertCmd cmd, TransferCmd transferCmd, BlockSeq trace, Model errModel, ModelViewInfo mvInfo, ProverContext context)
{
Contract.Requires(cmd != null);
Contract.Requires(transferCmd != null);
Contract.Requires(trace != null);
Contract.Requires(context != null);
- Contract.Requires(cce.NonNullDictionaryAndValues(incarnationOriginMap));
Contract.Ensures(Contract.Result<Counterexample>() != null);
List<string> relatedInformation = new List<string>();
@@ -3438,7 +3441,7 @@ namespace VC {
}
static VCExpr LetVC(Block startBlock,
- Variable controlFlowVariable,
+ VCExpr controlFlowVariableExpr,
Hashtable/*<int, Absy!>*/ label2absy,
ProverContext proverCtxt,
out int assertionCount) {
@@ -3449,12 +3452,12 @@ namespace VC {
Hashtable/*<Block, LetVariable!>*/ blockVariables = new Hashtable/*<Block, LetVariable!!>*/();
List<VCExprLetBinding> bindings = new List<VCExprLetBinding>();
- VCExpr startCorrect = LetVC(startBlock, controlFlowVariable, label2absy, blockVariables, bindings, proverCtxt, out assertionCount);
+ VCExpr startCorrect = LetVC(startBlock, controlFlowVariableExpr, label2absy, blockVariables, bindings, proverCtxt, out assertionCount);
return proverCtxt.ExprGen.Let(bindings, startCorrect);
}
static VCExpr LetVCIterative(List<Block> blocks,
- Variable controlFlowVariable,
+ VCExpr controlFlowVariableExpr,
Hashtable label2absy,
ProverContext proverCtxt,
out int assertionCount) {
@@ -3501,8 +3504,7 @@ namespace VC {
foreach (Block successor in gotocmd.labelTargets) {
Contract.Assert(successor != null);
VCExpr s = blockVariables[successor];
- if (controlFlowVariable != null) {
- VCExprVar controlFlowVariableExpr = proverCtxt.BoogieExprTranslator.LookupVariable(controlFlowVariable);
+ if (controlFlowVariableExpr != null) {
VCExpr controlFlowFunctionAppl = gen.ControlFlowFunctionApplication(controlFlowVariableExpr, gen.Integer(BigNum.FromInt(block.UniqueId)));
VCExpr controlTransferExpr = gen.Eq(controlFlowFunctionAppl, gen.Integer(BigNum.FromInt(successor.UniqueId)));
s = gen.Implies(controlTransferExpr, s);
@@ -3512,7 +3514,7 @@ namespace VC {
SuccCorrect = gen.NAry(VCExpressionGenerator.AndOp, SuccCorrectVars);
}
- VCContext context = new VCContext(label2absy, proverCtxt, controlFlowVariable);
+ VCContext context = new VCContext(label2absy, proverCtxt, controlFlowVariableExpr);
VCExpr vc = Wlp.Block(block, SuccCorrect, context);
assertionCount += context.AssertionCount;
@@ -3525,7 +3527,7 @@ namespace VC {
}
static VCExpr LetVC(Block block,
- Variable controlFlowVariable,
+ VCExpr controlFlowVariableExpr,
Hashtable/*<int, Absy!>*/ label2absy,
Hashtable/*<Block, VCExprVar!>*/ blockVariables,
List<VCExprLetBinding/*!*/>/*!*/ bindings,
@@ -3566,11 +3568,10 @@ namespace VC {
foreach (Block successor in gotocmd.labelTargets) {
Contract.Assert(successor != null);
int ac;
- VCExpr s = LetVC(successor, controlFlowVariable, label2absy, blockVariables, bindings, proverCtxt, out ac);
+ VCExpr s = LetVC(successor, controlFlowVariableExpr, label2absy, blockVariables, bindings, proverCtxt, out ac);
assertionCount += ac;
- if (controlFlowVariable != null)
+ if (controlFlowVariableExpr != null)
{
- VCExprVar controlFlowVariableExpr = proverCtxt.BoogieExprTranslator.LookupVariable(controlFlowVariable);
VCExpr controlFlowFunctionAppl = gen.ControlFlowFunctionApplication(controlFlowVariableExpr, gen.Integer(BigNum.FromInt(block.UniqueId)));
VCExpr controlTransferExpr = gen.Eq(controlFlowFunctionAppl, gen.Integer(BigNum.FromInt(successor.UniqueId)));
s = gen.Implies(controlTransferExpr, s);
@@ -3581,7 +3582,7 @@ namespace VC {
}
- VCContext context = new VCContext(label2absy, proverCtxt, controlFlowVariable);
+ VCContext context = new VCContext(label2absy, proverCtxt, controlFlowVariableExpr);
VCExpr vc = Wlp.Block(block, SuccCorrect, context);
assertionCount += context.AssertionCount;
@@ -3593,6 +3594,7 @@ namespace VC {
}
static VCExpr DagVC(Block block,
+ VCExpr controlFlowVariableExpr,
Hashtable/*<int, Absy!>*/ label2absy,
Hashtable/*<Block, VCExpr!>*/ blockEquations,
ProverContext proverCtxt,
@@ -3623,8 +3625,13 @@ namespace VC {
foreach (Block successor in cce.NonNull(gotocmd.labelTargets)) {
Contract.Assert(successor != null);
int ac;
- VCExpr c = DagVC(successor, label2absy, blockEquations, proverCtxt, out ac);
+ VCExpr c = DagVC(successor, controlFlowVariableExpr, label2absy, blockEquations, proverCtxt, out ac);
assertionCount += ac;
+ if (controlFlowVariableExpr != null) {
+ VCExpr controlFlowFunctionAppl = gen.ControlFlowFunctionApplication(controlFlowVariableExpr, gen.Integer(BigNum.FromInt(block.UniqueId)));
+ VCExpr controlTransferExpr = gen.Eq(controlFlowFunctionAppl, gen.Integer(BigNum.FromInt(successor.UniqueId)));
+ c = gen.Implies(controlTransferExpr, c);
+ }
SuccCorrect = SuccCorrect == null ? c : gen.And(SuccCorrect, c);
}
}
@@ -3632,7 +3639,7 @@ namespace VC {
SuccCorrect = VCExpressionGenerator.True;
}
- VCContext context = new VCContext(label2absy, proverCtxt);
+ VCContext context = new VCContext(label2absy, proverCtxt, controlFlowVariableExpr);
vc = Wlp.Block(block, SuccCorrect, context);
assertionCount += context.AssertionCount;
diff --git a/Source/VCGeneration/Wlp.cs b/Source/VCGeneration/Wlp.cs
index 94892c29..eb1ce4e1 100644
--- a/Source/VCGeneration/Wlp.cs
+++ b/Source/VCGeneration/Wlp.cs
@@ -22,7 +22,7 @@ namespace VC {
[Rep] public readonly Hashtable/*<int, Absy!>*/ Label2absy;
[Rep] public readonly ProverContext Ctxt;
- public readonly Variable ControlFlowVariable;
+ public readonly VCExpr ControlFlowVariableExpr;
public int AssertionCount; // counts the number of assertions for which Wlp has been computed
public VCContext(Hashtable/*<int, Absy!>*/ label2absy, ProverContext ctxt)
@@ -33,12 +33,12 @@ namespace VC {
// base();
}
- public VCContext(Hashtable/*<int, Absy!>*/ label2absy, ProverContext ctxt, Variable controlFlowVariable)
+ public VCContext(Hashtable/*<int, Absy!>*/ label2absy, ProverContext ctxt, VCExpr controlFlowVariableExpr)
{
Contract.Requires(ctxt != null);
this.Label2absy = label2absy;
this.Ctxt = ctxt;
- this.ControlFlowVariable = controlFlowVariable;
+ this.ControlFlowVariableExpr = controlFlowVariableExpr;
}
}
@@ -126,13 +126,11 @@ namespace VC {
return gen.Implies(C, N);
ctxt.AssertionCount++;
- if (ctxt.ControlFlowVariable == null) {
+ if (ctxt.ControlFlowVariableExpr == null) {
Contract.Assert(ctxt.Label2absy != null);
return gen.AndSimp(gen.LabelNeg(cce.NonNull(id.ToString()), C), N);
} else {
- VCExpr controlFlowVariableExpr = ctxt.Ctxt.BoogieExprTranslator.LookupVariable(ctxt.ControlFlowVariable);
- Contract.Assert(controlFlowVariableExpr != null);
- VCExpr controlFlowFunctionAppl = gen.ControlFlowFunctionApplication(controlFlowVariableExpr, gen.Integer(BigNum.FromInt(b.UniqueId)));
+ VCExpr controlFlowFunctionAppl = gen.ControlFlowFunctionApplication(ctxt.ControlFlowVariableExpr, gen.Integer(BigNum.FromInt(b.UniqueId)));
Contract.Assert(controlFlowFunctionAppl != null);
VCExpr assertFailure = gen.Eq(controlFlowFunctionAppl, gen.Integer(BigNum.FromInt(-ac.UniqueId)));
if (ctxt.Label2absy == null) {
diff --git a/Test/dafny0/Answer b/Test/dafny0/Answer
index d0dfc9be..9995c817 100644
--- a/Test/dafny0/Answer
+++ b/Test/dafny0/Answer
@@ -1445,7 +1445,7 @@ Execution trace:
(0,0): anon0
(0,0): anon11_Then
-Dafny program verifier finished with 13 verified, 2 errors
+Dafny program verifier finished with 19 verified, 2 errors
-------------------- Predicates.dfy --------------------
Predicates.dfy[B](18,5): Error BP5003: A postcondition might not hold on this return path.
@@ -1476,6 +1476,20 @@ Execution trace:
Dafny program verifier finished with 52 verified, 6 errors
+-------------------- Skeletons.dfy --------------------
+Skeletons.dfy(42,3): Error BP5003: A postcondition might not hold on this return path.
+Skeletons.dfy(41,15): Related location: This is the postcondition that might not hold.
+Execution trace:
+ (0,0): anon0
+ Skeletons.dfy[C0](29,5): anon12_LoopHead
+ (0,0): anon12_LoopBody
+ Skeletons.dfy[C0](29,5): anon13_Else
+ (0,0): anon9
+ Skeletons.dfy[C0](34,19): anon16_Else
+ (0,0): anon11
+
+Dafny program verifier finished with 9 verified, 1 error
+
-------------------- SmallTests.dfy --------------------
SmallTests.dfy(30,11): Error: index out of range
Execution trace:
@@ -1705,7 +1719,7 @@ Execution trace:
(0,0): anon0
(0,0): anon11_Then
-Dafny program verifier finished with 13 verified, 2 errors
+Dafny program verifier finished with 19 verified, 2 errors
out.tmp.dfy(10,12): Error: assertion violation
Execution trace:
(0,0): anon0
@@ -1714,4 +1728,4 @@ Execution trace:
(0,0): anon0
(0,0): anon11_Then
-Dafny program verifier finished with 13 verified, 2 errors
+Dafny program verifier finished with 19 verified, 2 errors
diff --git a/Test/dafny0/LetExpr.dfy b/Test/dafny0/LetExpr.dfy
index 48e4810b..11bf4fbe 100644
--- a/Test/dafny0/LetExpr.dfy
+++ b/Test/dafny0/LetExpr.dfy
@@ -107,3 +107,43 @@ method PMain(a: array<int>)
assert index == old(index) ==> a[index] == 21 && old(a[index]) == 19;
}
}
+
+// ---------- lemmas ----------
+
+method Theorem0(n: int)
+ requires 1 <= n;
+ ensures 1 <= Fib(n);
+{
+ if (n < 3) {
+ } else {
+ Theorem0(n-2);
+ Theorem0(n-1);
+ }
+}
+
+ghost method Theorem1(n: int)
+ requires 1 <= n;
+ ensures 1 <= Fib(n);
+{
+ // in a ghost method, the induction tactic takes care of it
+}
+
+function Theorem2(n: int): int
+ requires 1 <= n;
+ ensures 1 <= Fib(n);
+{
+ if n < 3 then 5 else
+ var x := Theorem2(n-2);
+ var y := Theorem2(n-1);
+ x + y
+}
+
+function Theorem3(n: int): int
+ requires 1 <= n;
+ ensures 1 <= Fib(n);
+{
+ if n < 3 then 5 else
+ var x := Theorem3(n-2);
+ var y := Theorem3(n-1);
+ 5
+}
diff --git a/Test/dafny0/Skeletons.dfy b/Test/dafny0/Skeletons.dfy
new file mode 100644
index 00000000..e9fef946
--- /dev/null
+++ b/Test/dafny0/Skeletons.dfy
@@ -0,0 +1,63 @@
+module A {
+ method M(p: int) returns (y: int)
+ requires p <= 30;
+ {
+ assume p < 100;
+ var x;
+ assume x == p + 20;
+ x := x + 1;
+ while (*)
+ invariant x <= 120;
+ decreases 120 - x;
+ {
+ if (x == 120) { break; }
+ x := x + 1;
+ }
+ y := x;
+ }
+}
+
+module B refines A {
+ method M ...
+ {
+ assert p < 50;
+ assert ...;
+ var x := p + 20;
+ assert ...;
+ var k := x + 1;
+ ...;
+ while ...
+ invariant k == x;
+ {
+ k := k + 1;
+ }
+ assert k == x || k == x + 1; // there are two exits from the loop
+ }
+}
+
+
+module C0 refines B {
+ method M ...
+ ensures y == 120; // error: this holds only if the loop does not end early
+ {
+ }
+}
+
+module C1 refines B {
+ method M ...
+ ensures y <= 120;
+ {
+ }
+}
+
+module C2 refines B {
+ method M ...
+ ensures y == 120;
+ {
+ ...;
+ while (true)
+ ...
+ assert k == x + 1; // only one loop exit remains
+ ...;
+ }
+}
diff --git a/Test/dafny0/runtest.bat b/Test/dafny0/runtest.bat
index b1402e83..608b7358 100644
--- a/Test/dafny0/runtest.bat
+++ b/Test/dafny0/runtest.bat
@@ -22,7 +22,7 @@ for %%f in (TypeTests.dfy NatTypes.dfy SmallTests.dfy Definedness.dfy
LoopModifies.dfy Refinement.dfy RefinementErrors.dfy
ReturnErrors.dfy ReturnTests.dfy ChainingDisjointTests.dfy
CallStmtTests.dfy MultiSets.dfy PredExpr.dfy LetExpr.dfy
- Predicates.dfy) do (
+ Predicates.dfy Skeletons.dfy) do (
echo.
echo -------------------- %%f --------------------
%DAFNY_EXE% /compile:0 /print:out.bpl.tmp /dprint:out.dfy.tmp %* %%f
diff --git a/Test/dafny1/Answer b/Test/dafny1/Answer
index ab10d944..023d80df 100644
--- a/Test/dafny1/Answer
+++ b/Test/dafny1/Answer
@@ -15,6 +15,10 @@ Dafny program verifier finished with 24 verified, 0 errors
Dafny program verifier finished with 11 verified, 0 errors
+-------------------- ExtensibleArrayAuto.dfy --------------------
+
+Dafny program verifier finished with 11 verified, 0 errors
+
-------------------- BinaryTree.dfy --------------------
Dafny program verifier finished with 24 verified, 0 errors
diff --git a/Test/dafny1/ExtensibleArrayAuto.dfy b/Test/dafny1/ExtensibleArrayAuto.dfy
new file mode 100644
index 00000000..f7f97deb
--- /dev/null
+++ b/Test/dafny1/ExtensibleArrayAuto.dfy
@@ -0,0 +1,113 @@
+class {:autocontracts} ExtensibleArray<T> {
+ ghost var Contents: seq<T>;
+
+ var elements: array<T>;
+ var more: ExtensibleArray<array<T>>;
+ var length: int;
+ var M: int; // shorthand for: if more == null then 0 else 256 * |more.Contents|
+
+ function Valid(): bool
+ {
+ // shape of data structure
+ elements != null && elements.Length == 256 &&
+ (more != null ==>
+ elements !in more.Repr &&
+ more.Valid() &&
+ |more.Contents| != 0 &&
+ forall j :: 0 <= j && j < |more.Contents| ==>
+ more.Contents[j] != null && more.Contents[j].Length == 256 &&
+ more.Contents[j] in Repr && more.Contents[j] !in more.Repr &&
+ more.Contents[j] != elements &&
+ forall k :: 0 <= k && k < |more.Contents| && k != j ==> more.Contents[j] != more.Contents[k]) &&
+
+ // length
+ M == (if more == null then 0 else 256 * |more.Contents|) &&
+ 0 <= length && length <= M + 256 &&
+ (more != null ==> M < length) &&
+
+ // Contents
+ length == |Contents| &&
+ (forall i :: 0 <= i && i < M ==> Contents[i] == more.Contents[i / 256][i % 256]) &&
+ (forall i :: M <= i && i < length ==> Contents[i] == elements[i - M])
+ }
+
+ constructor Init()
+ ensures Contents == [];
+ {
+ elements := new T[256];
+ more := null;
+ length := 0;
+ M := 0;
+
+ Contents := [];
+ }
+
+ method Get(i: int) returns (t: T)
+ requires 0 <= i && i < |Contents|;
+ ensures t == Contents[i];
+ decreases Repr;
+ {
+ if (M <= i) {
+ t := elements[i - M];
+ } else {
+ var arr := more.Get(i / 256);
+ t := arr[i % 256];
+ }
+ }
+
+ method Set(i: int, t: T)
+ requires 0 <= i && i < |Contents|;
+ ensures Contents == old(Contents)[i := t];
+ {
+ if (M <= i) {
+ elements[i - M] := t;
+ } else {
+ var arr := more.Get(i / 256);
+ arr[i % 256] := t;
+ }
+ Contents := Contents[i := t];
+ }
+
+ method Append(t: T)
+ ensures Contents == old(Contents) + [t];
+ decreases Repr;
+ {
+ if (length == 0 || length % 256 != 0) {
+ // there is room in "elements"
+ elements[length - M] := t;
+ } else {
+ if (more == null) {
+ more := new ExtensibleArray<array<T>>.Init();
+ Repr := Repr + {more} + more.Repr;
+ }
+ // "elements" is full, so move it into "more" and allocate a new array
+ more.Append(elements);
+ Repr := Repr + more.Repr;
+ M := M + 256;
+ elements := new T[256];
+ Repr := Repr + {elements};
+ elements[0] := t;
+ }
+ length := length + 1;
+ Contents := Contents + [t];
+ }
+}
+
+method Main() {
+ var a := new ExtensibleArray<int>.Init();
+ var n := 0;
+ while (n < 256*256+600)
+ invariant a.Valid() && fresh(a.Repr);
+ invariant |a.Contents| == n;
+ {
+ a.Append(n);
+ n := n + 1;
+ }
+ var k := a.Get(570); print k, "\n";
+ k := a.Get(0); print k, "\n";
+ k := a.Get(1000); print k, "\n";
+ a.Set(1000, 23);
+ k := a.Get(0); print k, "\n";
+ k := a.Get(1000); print k, "\n";
+ k := a.Get(66000); print k, "\n";
+}
diff --git a/Test/dafny1/runtest.bat b/Test/dafny1/runtest.bat
index 524765cf..0ad75ffa 100644
--- a/Test/dafny1/runtest.bat
+++ b/Test/dafny1/runtest.bat
@@ -12,7 +12,8 @@ for %%f in (BQueue.bpl) do (
%BPLEXE% %* %%f
)
-for %%f in (Queue.dfy PriorityQueue.dfy ExtensibleArray.dfy
+for %%f in (Queue.dfy PriorityQueue.dfy
+ ExtensibleArray.dfy ExtensibleArrayAuto.dfy
BinaryTree.dfy
UnboundedStack.dfy
SeparationLogicList.dfy
diff --git a/Test/houdini/Answer b/Test/houdini/Answer
index 6053b442..d7edbce6 100644
--- a/Test/houdini/Answer
+++ b/Test/houdini/Answer
@@ -9,6 +9,10 @@ Boogie program verifier finished with 1 verified, 0 errors
Assignment computed by Houdini:
b1 = False
b2 = True
+houd2.bpl(12,1): Error BP5003: A postcondition might not hold on this return path.
+houd2.bpl(9,1): Related location: This is the postcondition that might not hold.
+Execution trace:
+ houd2.bpl(11,3): anon0
Boogie program verifier finished with 1 verified, 1 error
@@ -72,6 +76,9 @@ Assignment computed by Houdini:
b1 = True
b2 = True
b3 = True
+houd9.bpl(19,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ houd9.bpl(18,9): anon0
Boogie program verifier finished with 0 verified, 1 error
@@ -80,11 +87,18 @@ Assignment computed by Houdini:
b1 = True
b2 = True
b3 = True
+houd10.bpl(15,3): Error BP5002: A precondition for this call might not hold.
+houd10.bpl(20,1): Related location: This is the precondition that might not hold.
+Execution trace:
+ houd10.bpl(14,9): anon0
Boogie program verifier finished with 0 verified, 1 error
-------------------- houd11.bpl --------------------
Assignment computed by Houdini:
+houd11.bpl(8,3): Error BP5001: This assertion might not hold.
+Execution trace:
+ houd11.bpl(7,9): anon0
Boogie program verifier finished with 0 verified, 1 error
diff --git a/Test/houdini/runtest.bat b/Test/houdini/runtest.bat
index f0065b0d..b9816bb9 100644
--- a/Test/houdini/runtest.bat
+++ b/Test/houdini/runtest.bat
@@ -6,11 +6,11 @@ set BGEXE=..\..\Binaries\Boogie.exe
for %%f in (houd1.bpl houd2.bpl houd3.bpl houd4.bpl houd5.bpl houd6.bpl houd7.bpl houd8.bpl houd9.bpl houd10.bpl houd11.bpl houd12.bpl) do (
echo.
echo -------------------- %%f --------------------
- %BGEXE% %* /nologo /noinfer /contractInfer %%f
+ %BGEXE% %* /nologo /noinfer /contractInfer /printAssignment %%f
)
for %%f in (test1.bpl test2.bpl test7.bpl test8.bpl test9.bpl test10.bpl) do (
echo .
echo -------------------- %%f --------------------
- %BGEXE% %* /nologo /noinfer /contractInfer /inlineDepth:1 %%f
+ %BGEXE% %* /nologo /noinfer /contractInfer /printAssignment /inlineDepth:1 %%f
)
diff --git a/Test/vstte2012/Answer b/Test/vstte2012/Answer
index 15a95de1..bca270c3 100644
--- a/Test/vstte2012/Answer
+++ b/Test/vstte2012/Answer
@@ -11,6 +11,10 @@ Dafny program verifier finished with 25 verified, 0 errors
Dafny program verifier finished with 13 verified, 0 errors
+-------------------- RingBufferAuto.dfy --------------------
+
+Dafny program verifier finished with 13 verified, 0 errors
+
-------------------- Tree.dfy --------------------
Dafny program verifier finished with 15 verified, 0 errors
diff --git a/Test/vstte2012/RingBufferAuto.dfy b/Test/vstte2012/RingBufferAuto.dfy
new file mode 100644
index 00000000..712236a8
--- /dev/null
+++ b/Test/vstte2012/RingBufferAuto.dfy
@@ -0,0 +1,75 @@
+class {:autocontracts} RingBuffer<T>
+{
+ // public view of the class:
+ ghost var Contents: seq<T>; // the contents of the ring buffer
+ ghost var N: nat; // the capacity of the ring buffer
+
+ // private implementation:
+ var data: array<T>;
+ var first: nat;
+ var len: nat;
+
+ // Valid encodes the consistency of RingBuffer objects (think, invariant)
+ predicate Valid
+ {
+ data != null &&
+ data.Length == N &&
+ (N == 0 ==> len == first == 0 && Contents == []) &&
+ (N != 0 ==> len <= N && first < N) &&
+ Contents == if first + len <= N then data[first..first+len]
+ else data[first..] + data[..first+len-N]
+ }
+
+ constructor Create(n: nat)
+ ensures Contents == [] && N == n;
+ {
+ data := new T[n];
+ first, len := 0, 0;
+ Contents, N := [], n;
+ }
+
+ method Clear()
+ ensures Contents == [] && N == old(N);
+ {
+ len := 0;
+ Contents := [];
+ }
+
+ method Head() returns (x: T)
+ requires Contents != [];
+ ensures x == Contents[0];
+ {
+ x := data[first];
+ }
+
+ method Enqueue(x: T)
+ requires |Contents| != N;
+ ensures Contents == old(Contents) + [x] && N == old(N);
+ {
+ var nextEmpty := if first + len < data.Length
+ then first + len else first + len - data.Length;
+ data[nextEmpty] := x;
+ len := len + 1;
+ Contents := Contents + [x];
+ }
+
+ method Dequeue() returns (x: T)
+ requires Contents != [];
+ ensures x == old(Contents)[0] && Contents == old(Contents)[1..] && N == old(N);
+ {
+ x := data[first];
+ first, len := if first + 1 == data.Length then 0 else first + 1, len - 1;
+ Contents := Contents[1..];
+ }
+}
+
+method TestHarness(x: int, y: int, z: int)
+{
+ var b := new RingBuffer.Create(2);
+ b.Enqueue(x);
+ b.Enqueue(y);
+ var h := b.Dequeue(); assert h == x;
+ b.Enqueue(z);
+ h := b.Dequeue(); assert h == y;
+ h := b.Dequeue(); assert h == z;
+}
diff --git a/Test/vstte2012/runtest.bat b/Test/vstte2012/runtest.bat
index 5145cb56..770f41dc 100644
--- a/Test/vstte2012/runtest.bat
+++ b/Test/vstte2012/runtest.bat
@@ -8,7 +8,7 @@ set CSC=c:/Windows/Microsoft.NET/Framework/v4.0.30319/csc.exe
for %%f in (
Two-Way-Sort.dfy
Combinators.dfy
- RingBuffer.dfy
+ RingBuffer.dfy RingBufferAuto.dfy
Tree.dfy
BreadthFirstSearch.dfy
) do (
diff --git a/_admin/Boogie/aste/summary.log b/_admin/Boogie/aste/summary.log
index 23b26040..0ae312c7 100644
--- a/_admin/Boogie/aste/summary.log
+++ b/_admin/Boogie/aste/summary.log
@@ -1,15 +1,15 @@
-# Aste started: 2012-02-08 07:00:05
+# Aste started: 2012-03-01 07:00:05
# Host id: Boogiebox
# Configuration: boogie.cfg
# Task: aste.tasks.boogie.FullBuild
-# [2012-02-08 07:03:10] SpecSharp revision: 3fe48f1c3eb0
-# [2012-02-08 07:03:10] SscBoogie revision: 3fe48f1c3eb0
-# [2012-02-08 07:05:07] Boogie revision: c67a7a83262e
-[2012-02-08 07:06:44] C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\devenv.com SpecSharp.sln /Project "Checkin Tests" /Build
+# [2012-03-01 07:02:56] SpecSharp revision: efcb0d478c80
+# [2012-03-01 07:02:56] SscBoogie revision: efcb0d478c80
+# [2012-03-01 07:04:55] Boogie revision: 755664b13a88
+[2012-03-01 07:06:33] C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\devenv.com SpecSharp.sln /Project "Checkin Tests" /Build
1>corflags : warning CF011: The specified file is strong name signed. Using /Force will invalidate the signature of this image and will require the assembly to be resigned.
warning CF011: The specified file is strong name signed. Using /Force will invalidate the signature of this image and will require the assembly to be resigned.
-[2012-02-08 07:08:28] C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\devenv.com Boogie.sln /Rebuild Checked
+[2012-03-01 07:07:54] C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\devenv.com Boogie.sln /Rebuild Checked
D:\Temp\aste\Boogie\Source\Core\AbsyType.cs(823,16): warning CS0659: 'Microsoft.Boogie.BasicType' overrides Object.Equals(object o) but does not override Object.GetHashCode()
D:\Temp\aste\Boogie\Source\Core\AbsyType.cs(2802,16): warning CS0659: 'Microsoft.Boogie.CtorType' overrides Object.Equals(object o) but does not override Object.GetHashCode()
@@ -22,9 +22,8 @@
D:\Temp\aste\Boogie\Source\AbsInt\ExprFactories.cs(247,7): warning CS0162: Unreachable code detected
D:\Temp\aste\Boogie\Source\AbsInt\ExprFactories.cs(266,7): warning CS0162: Unreachable code detected
D:\Temp\aste\Boogie\Source\AbsInt\IntervalDomain.cs(49,9): warning CC1036: Detected call to method 'Microsoft.Boogie.AbstractInterpretation.NativeIntervallDomain+Node.StrictlyBefore(Microsoft.Boogie.Variable,Microsoft.Boogie.Variable)' without [Pure] in contracts of method 'Microsoft.Boogie.AbstractInterpretation.NativeIntervallDomain+Node.#ctor(Microsoft.Boogie.Variable,System.Nullable`1<System.Numerics.BigInteger>,System.Nullable`1<System.Numerics.BigInteger>,Microsoft.Boogie.AbstractInterpretation.NativeIntervallDomain+Node)'.
- D:\Temp\aste\Boogie\Source\VCGeneration\VC.cs(1697,11): warning CS0162: Unreachable code detected
- D:\Temp\aste\Boogie\Source\VCGeneration\VC.cs(1858,11): warning CS0162: Unreachable code detected
- D:\Temp\aste\Boogie\Source\VCGeneration\StratifiedVC.cs(1095,17): warning CC1032: Method 'VC.StratifiedVCGen+NormalChecker.CheckVC' overrides 'VC.StratifiedVCGen+StratifiedCheckerInterface.CheckVC', thus cannot add Requires.
+ D:\Temp\aste\Boogie\Source\VCGeneration\VC.cs(1717,11): warning CS0162: Unreachable code detected
+ D:\Temp\aste\Boogie\Source\VCGeneration\VC.cs(1878,11): warning CS0162: Unreachable code detected
EXEC : warning CC1032: Method 'Microsoft.Boogie.Houdini.InlineRequiresVisitor.VisitCmdSeq(Microsoft.Boogie.CmdSeq)' overrides 'Microsoft.Boogie.StandardVisitor.VisitCmdSeq(Microsoft.Boogie.CmdSeq)', thus cannot add Requires.
EXEC : warning CC1032: Method 'Microsoft.Boogie.Houdini.FreeRequiresVisitor.VisitAssertRequiresCmd(Microsoft.Boogie.AssertRequiresCmd)' overrides 'Microsoft.Boogie.StandardVisitor.VisitAssertRequiresCmd(Microsoft.Boogie.AssertRequiresCmd)', thus cannot add Requires.
warning CS0659: 'Microsoft.Boogie.BasicType' overrides Object.Equals(object o) but does not override Object.GetHashCode()
@@ -40,8 +39,7 @@
warning CC1036: Detected call to method 'Microsoft.Boogie.AbstractInterpretation.NativeIntervallDomain+Node.StrictlyBefore(Microsoft.Boogie.Variable,Microsoft.Boogie.Variable)' without [Pure] in contracts of method 'Microsoft.Boogie.AbstractInterpretation.NativeIntervallDomain+Node.#ctor(Microsoft.Boogie.Variable,System.Nullable`1<System.Numerics.BigInteger>,System.Nullable`1<System.Numerics.BigInteger>,Microsoft.Boogie.AbstractInterpretation.NativeIntervallDomain+Node)'.
warning CS0162: Unreachable code detected
warning CS0162: Unreachable code detected
- warning CC1032: Method 'VC.StratifiedVCGen+NormalChecker.CheckVC' overrides 'VC.StratifiedVCGen+StratifiedCheckerInterface.CheckVC', thus cannot add Requires.
warning CC1032: Method 'Microsoft.Boogie.Houdini.InlineRequiresVisitor.VisitCmdSeq(Microsoft.Boogie.CmdSeq)' overrides 'Microsoft.Boogie.StandardVisitor.VisitCmdSeq(Microsoft.Boogie.CmdSeq)', thus cannot add Requires.
warning CC1032: Method 'Microsoft.Boogie.Houdini.FreeRequiresVisitor.VisitAssertRequiresCmd(Microsoft.Boogie.AssertRequiresCmd)' overrides 'Microsoft.Boogie.StandardVisitor.VisitAssertRequiresCmd(Microsoft.Boogie.AssertRequiresCmd)', thus cannot add Requires.
-[2012-02-08 08:05:37] 0 out of 33 test(s) in D:\Temp\aste\Boogie\Test\alltests.txt failed
-# [2012-02-08 08:06:21] Released nightly of Boogie
+[2012-03-01 08:04:53] 0 out of 33 test(s) in D:\Temp\aste\Boogie\Test\alltests.txt failed
+# [2012-03-01 08:05:34] Released nightly of Boogie