diff options
author | chmaria <unknown> | 2012-06-18 15:00:48 +0200 |
---|---|---|
committer | chmaria <unknown> | 2012-06-18 15:00:48 +0200 |
commit | 6e0e8b16609329816c07c7ef451479861ed89abe (patch) | |
tree | c6e60423355816f52b0633f2bcca5cdda5732733 | |
parent | c0f50ec423987b670181d13a416c1bffd279556a (diff) | |
parent | 0788f5ea2bb20f079ffa5294d52fe76b78c74fa9 (diff) |
Merged with default.
102 files changed, 3525 insertions, 2446 deletions
diff --git a/BCT/BytecodeTranslator/ExpressionTraverser.cs b/BCT/BytecodeTranslator/ExpressionTraverser.cs index 70db8512..b2d23777 100644 --- a/BCT/BytecodeTranslator/ExpressionTraverser.cs +++ b/BCT/BytecodeTranslator/ExpressionTraverser.cs @@ -995,6 +995,7 @@ namespace BytecodeTranslator cmd = Bpl.Cmd.SimpleAssign(tok, bplLocal, e);
}
StmtTraverser.StmtBuilder.Add(cmd);
+ this.TranslatedExpressions.Push(e); // value of assignment might be needed for an enclosing expression
return;
}
@@ -1010,6 +1011,7 @@ namespace BytecodeTranslator cmd = Bpl.Cmd.SimpleAssign(tok, bplParam, e);
}
StmtTraverser.StmtBuilder.Add(cmd);
+ this.TranslatedExpressions.Push(e); // value of assignment might be needed for an enclosing expression
return;
}
@@ -1029,6 +1031,7 @@ namespace BytecodeTranslator StmtTraverser.StmtBuilder.Add(this.sink.Heap.WriteHeap(tok, x, f, e,
field.ResolvedField.ContainingType.ResolvedType.IsStruct ? AccessType.Struct : AccessType.Heap,
boogieType));
+ this.TranslatedExpressions.Push(e); // value of assignment might be needed for an enclosing expression
}
return;
}
@@ -1042,6 +1045,7 @@ namespace BytecodeTranslator this.Traverse(source);
var e = this.TranslatedExpressions.Pop();
StmtTraverser.StmtBuilder.Add(sink.Heap.WriteHeap(Bpl.Token.NoToken, x, indices_prime, e, AccessType.Array, sink.CciTypeToBoogie(arrayIndexer.Type)));
+ this.TranslatedExpressions.Push(e); // value of assignment might be needed for an enclosing expression
return;
}
@@ -1083,6 +1087,7 @@ namespace BytecodeTranslator var bplLocal = Bpl.Expr.Ident(this.sink.ThisVariable);
cmd = Bpl.Cmd.SimpleAssign(tok, bplLocal, e);
StmtTraverser.StmtBuilder.Add(cmd);
+ this.TranslatedExpressions.Push(e); // value of assignment might be needed for an enclosing expression
return;
}
}
diff --git a/BCT/BytecodeTranslator/Program.cs b/BCT/BytecodeTranslator/Program.cs index cf758611..ffee13eb 100644 --- a/BCT/BytecodeTranslator/Program.cs +++ b/BCT/BytecodeTranslator/Program.cs @@ -295,6 +295,7 @@ namespace BytecodeTranslator { if (module == null || module == Dummy.Module || module == Dummy.Assembly) {
Console.WriteLine(a + " is not a PE file containing a CLR module or assembly, or an error occurred when loading it.");
Console.WriteLine("Skipping it, continuing with other input assemblies");
+ continue;
}
modules.Add(module);
}
diff --git a/Binaries/DafnyPrelude.bpl b/Binaries/DafnyPrelude.bpl index 742fd4e4..fef8fe1f 100644 --- a/Binaries/DafnyPrelude.bpl +++ b/Binaries/DafnyPrelude.bpl @@ -558,6 +558,11 @@ axiom (forall x: int, h: HeapType :: axiom (forall r: ref, h: HeapType ::
{ GenericAlloc($Box(r), h) }
$IsGoodHeap(h) && (r == null || h[r,alloc]) ==> GenericAlloc($Box(r), h));
+// boxes in the heap
+axiom (forall r: ref, f: Field BoxType, h: HeapType ::
+ { GenericAlloc(read(h, r, f), h) }
+ $IsGoodHeap(h) && r != null && read(h, r, alloc) ==>
+ GenericAlloc(read(h, r, f), h));
// ---------------------------------------------------------------
// -- Arrays -----------------------------------------------------
diff --git a/Binaries/DafnyRuntime.cs b/Binaries/DafnyRuntime.cs index f7eecfc5..61df448f 100644 --- a/Binaries/DafnyRuntime.cs +++ b/Binaries/DafnyRuntime.cs @@ -1,8 +1,9 @@ using System.Numerics;
-using System.Collections.Generic;
namespace Dafny
{
+ using System.Collections.Generic;
+
public class Set<T>
{
Dictionary<T, bool> dict;
diff --git a/Chalice/src/main/scala/Prelude.scala b/Chalice/src/main/scala/Prelude.scala index 721b0131..f54cee2c 100644 --- a/Chalice/src/main/scala/Prelude.scala +++ b/Chalice/src/main/scala/Prelude.scala @@ -137,15 +137,11 @@ object CreditsAndMuPL extends PreludeComponent { val text = """
var Credits: CreditsType;
-function IsGoodState(PartialHeapType) returns (bool);
function combine(PartialHeapType, PartialHeapType) returns (PartialHeapType);
function heapFragment<T>(T) returns (PartialHeapType);
type PartialHeapType;
const emptyPartialHeap: PartialHeapType;
-axiom (forall a: PartialHeapType, b: PartialHeapType :: {IsGoodState(combine(a, b))} IsGoodState(combine(a, b)) <==> IsGoodState(a) && IsGoodState(b));
-axiom IsGoodState(emptyPartialHeap);
-
type ModuleName;
const CurrentModule: ModuleName;
type TypeName;
diff --git a/Chalice/src/main/scala/Resolver.scala b/Chalice/src/main/scala/Resolver.scala index e802b7e7..dda5d989 100644 --- a/Chalice/src/main/scala/Resolver.scala +++ b/Chalice/src/main/scala/Resolver.scala @@ -232,6 +232,7 @@ object Resolver { if (!e.typ.IsBool) context.Error(c.pos, "where clause requires a boolean expression (found " + e.typ.FullName + ")")
case p@Predicate(id, e) =>
var ctx = context;
+ if (ContainsWaitlevel(e)) context.Error(e.pos, "predicate body is not allowed to mention 'waitlevel'")
ResolveExpr(e, ctx, false, true)(true);
if(!e.typ.IsBool) context.Error(e.pos, "predicate requires a boolean expression (found " + e.typ.FullName + ")")
case f@Function(id, ins, out, spec, definition) =>
@@ -862,6 +863,18 @@ object Resolver { )
x
}
+
+ // does e contain 'waitlevel'?
+ def ContainsWaitlevel(expr: Expression): Boolean = {
+ var x: Boolean = false
+ AST.visit(expr,
+ e => e match {
+ case _:MaxLockLiteral => x = true
+ case _ =>
+ }
+ )
+ x
+ }
// ResolveExpr resolves all parts of an RValue, if possible, and (always) sets the RValue's typ field
def ResolveExpr(e: RValue, context: ProgramContext,
diff --git a/Chalice/src/main/scala/Translator.scala b/Chalice/src/main/scala/Translator.scala index bd4f3e10..94d44d9e 100644 --- a/Chalice/src/main/scala/Translator.scala +++ b/Chalice/src/main/scala/Translator.scala @@ -265,7 +265,7 @@ class Translator { // Encoding with heapFragment and combine
/* function ##C.f(state, ref, t_1, ..., t_n) returns (t);
axiom (forall h: HeapType, m, sm: MaskType, this: ref, x_1: t_1, ..., x_n: t_n ::
- wf(h, m, sm) && IsGoodState(partialHeap) ==> #C.f(h, m, sm, this, x_1, ..., x_n) == ##C.f(partialHeap, this, x_1, ..., x_n))
+ wf(h, m, sm) ==> #C.f(h, m, sm, this, x_1, ..., x_n) == ##C.f(partialHeap, this, x_1, ..., x_n))
*/
val partialHeap = functionDependencies(pre, etran);
val inArgs = (f.ins map {i => Boogie.VarExpr(i.UniqueName)});
@@ -280,7 +280,7 @@ class Translator { Axiom(new Boogie.Forall(
BVar(HeapName, theap) :: BVar(MaskName, tmask) :: BVar(SecMaskName, tmask) :: BVar("this", tref) :: (f.ins map Variable2BVar),
new Trigger(List(applyF, wellformed)),
- (wellformed && IsGoodState(partialHeap) && CanAssumeFunctionDefs)
+ (wellformed && CanAssumeFunctionDefs)
==>
(applyF ==@ applyFrameFunction))
)
@@ -1959,7 +1959,6 @@ class ExpressionTranslator(val globals: Globals, preGlobals: Globals, val fpi: F (if(e.isPredicate) Nil else List(bassume(TypeInformation(new Boogie.MapSelect(Heap, trE, memberName), e.f.typ.typ)))) :::
InhalePermission(perm, trE, memberName, currentK, (if (transferToSecMask) SecMask else Mask)) :::
bassume(AreGoodMasks(Mask, SecMask)) ::
- bassume(IsGoodState(heapFragment(new Boogie.MapSelect(ih, trE, memberName)))) ::
bassume(wf(Heap, Mask, SecMask)) ::
bassume(wf(ih, Mask, SecMask))
case acc @ AccessSeq(s, Some(member), perm) =>
@@ -2031,7 +2030,6 @@ class ExpressionTranslator(val globals: Globals, preGlobals: Globals, val fpi: F bassert(nonNull(trE), holds.pos, "The target of the holds predicate might be null.")
else Nil) :::
bassume(AreGoodMasks(Mask, SecMask)) ::
- bassume(IsGoodState(heapFragment(new Boogie.MapSelect(ih, trE, "held")))) ::
bassume(wf(Heap, Mask, SecMask)) ::
bassume(wf(ih, Mask, SecMask)) ::
new Boogie.MapUpdate(Heap, trE, VarExpr("held"),
@@ -2041,7 +2039,6 @@ class ExpressionTranslator(val globals: Globals, preGlobals: Globals, val fpi: F bassume(new Boogie.MapSelect(ih, trE, "mu") !=@ bLockBottom) ::
bassume(wf(Heap, Mask, SecMask)) ::
bassume(AreGoodMasks(Mask, SecMask)) ::
- bassume(IsGoodState(heapFragment(new Boogie.MapSelect(ih, trE, "held")))) ::
bassume(wf(Heap, Mask, SecMask)) ::
bassume(wf(ih, Mask, SecMask))
case Eval(h, e) =>
@@ -2067,7 +2064,7 @@ class ExpressionTranslator(val globals: Globals, preGlobals: Globals, val fpi: F bassume(preEtran.Heap ==@ evalHeap) ::
bassume(submask(preEtran.Mask, evalMask))
case uf@Unfolding(acc@Access(pred@MemberAccess(obj, f), perm), ufexpr) =>
- if (transferToSecMask) throw new NotSupportedException("not yet implemented")
+ if (transferToSecMask) return Nil
// handle unfolding like the next case, but also record permissions of the predicate
// in the secondary mask and track the predicate in the auxilary information
val (receiverV, receiver) = Boogie.NewBVar("predRec", tref, true)
@@ -2761,7 +2758,6 @@ object TranslationHelper { def monitorK = "monitorK";
def predicateK = "predicateK";
def CurrentModule = VarExpr("CurrentModule");
- def IsGoodState(e: Expr) = FunctionApp("IsGoodState", List(e));
def dtype(e: Expr) = FunctionApp("dtype", List(e))
def functionName(f: Function) = "#" + f.FullName;
def className(cl: Class) = Boogie.VarExpr(cl.id + "#t")
diff --git a/Chalice/tests/regressions/workitem-10222.chalice b/Chalice/tests/regressions/workitem-10222.chalice new file mode 100644 index 00000000..a01253c9 --- /dev/null +++ b/Chalice/tests/regressions/workitem-10222.chalice @@ -0,0 +1,8 @@ +class Test { + var t: Test; + + // previously, mentioning "waitlevel" in a predicate did not cause an error + predicate inv { + acc(t) && acc(t.mu) && t.mu << waitlevel + } +} diff --git a/Chalice/tests/regressions/workitem-10222.output.txt b/Chalice/tests/regressions/workitem-10222.output.txt new file mode 100644 index 00000000..eac18363 --- /dev/null +++ b/Chalice/tests/regressions/workitem-10222.output.txt @@ -0,0 +1,4 @@ +Verification of workitem-10222.chalice using parameters=""
+
+The program did not typecheck.
+6.9: predicate body is not allowed to mention 'waitlevel'
diff --git a/Chalice/tests/regressions/workitem-10223.chalice b/Chalice/tests/regressions/workitem-10223.chalice new file mode 100644 index 00000000..eb4bd00b --- /dev/null +++ b/Chalice/tests/regressions/workitem-10223.chalice @@ -0,0 +1,8 @@ +class Lala { + var next: Lala; + var x: int; + predicate inv { + acc(next) && acc(x) && + (next != null ==> (next.inv && unfolding next.inv in this.x > next.x)) + } +} diff --git a/Chalice/tests/regressions/workitem-10223.output.txt b/Chalice/tests/regressions/workitem-10223.output.txt new file mode 100644 index 00000000..f4bfd78d --- /dev/null +++ b/Chalice/tests/regressions/workitem-10223.output.txt @@ -0,0 +1,4 @@ +Verification of workitem-10223.chalice using parameters=""
+
+ +Boogie program verifier finished with 0 errors and 0 smoke test warnings.
diff --git a/Source/AbsInt/AbsInt.csproj b/Source/AbsInt/AbsInt.csproj index 93d304d7..9ccd0ffe 100644 --- a/Source/AbsInt/AbsInt.csproj +++ b/Source/AbsInt/AbsInt.csproj @@ -141,6 +141,67 @@ <CodeContractsReferenceAssembly>Build</CodeContractsReferenceAssembly>
<CodeContractsAnalysisWarningLevel>0</CodeContractsAnalysisWarningLevel>
</PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\x86\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>x86</PlatformTarget>
+ <CodeAnalysisLogFile>bin\Debug\AbsInt.dll.CodeAnalysisLog.xml</CodeAnalysisLogFile>
+ <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
+ <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
+ <CodeAnalysisIgnoreBuiltInRuleSets>true</CodeAnalysisIgnoreBuiltInRuleSets>
+ <CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
+ <CodeAnalysisIgnoreBuiltInRules>true</CodeAnalysisIgnoreBuiltInRules>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
+ <OutputPath>bin\x86\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <Optimize>true</Optimize>
+ <DebugType>pdbonly</DebugType>
+ <PlatformTarget>x86</PlatformTarget>
+ <CodeAnalysisLogFile>bin\Release\AbsInt.dll.CodeAnalysisLog.xml</CodeAnalysisLogFile>
+ <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
+ <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
+ <CodeAnalysisIgnoreBuiltInRuleSets>true</CodeAnalysisIgnoreBuiltInRuleSets>
+ <CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
+ <CodeAnalysisIgnoreBuiltInRules>true</CodeAnalysisIgnoreBuiltInRules>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'z3apidebug|x86'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\x86\z3apidebug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>x86</PlatformTarget>
+ <CodeAnalysisLogFile>bin\z3apidebug\AbsInt.dll.CodeAnalysisLog.xml</CodeAnalysisLogFile>
+ <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
+ <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>Migrated rules for AbsInt.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
+ <CodeAnalysisIgnoreBuiltInRuleSets>false</CodeAnalysisIgnoreBuiltInRuleSets>
+ <CodeAnalysisIgnoreBuiltInRules>true</CodeAnalysisIgnoreBuiltInRules>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Checked|x86'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\x86\Checked\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>x86</PlatformTarget>
+ <CodeAnalysisLogFile>bin\Debug\AbsInt.dll.CodeAnalysisLog.xml</CodeAnalysisLogFile>
+ <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
+ <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
+ <CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
+ </PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core">
diff --git a/Source/Boogie.sln b/Source/Boogie.sln index 955dfb46..1e733880 100644 --- a/Source/Boogie.sln +++ b/Source/Boogie.sln @@ -79,7 +79,8 @@ Global {DAB6BAA4-7AF7-449F-96AB-F58F34D03A7A}.z3apidebug|Any CPU.Build.0 = z3apidebug|Any CPU
{DAB6BAA4-7AF7-449F-96AB-F58F34D03A7A}.z3apidebug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{DAB6BAA4-7AF7-449F-96AB-F58F34D03A7A}.z3apidebug|Mixed Platforms.Build.0 = Debug|Any CPU
- {DAB6BAA4-7AF7-449F-96AB-F58F34D03A7A}.z3apidebug|x86.ActiveCfg = z3apidebug|Any CPU
+ {DAB6BAA4-7AF7-449F-96AB-F58F34D03A7A}.z3apidebug|x86.ActiveCfg = z3apidebug|x86
+ {DAB6BAA4-7AF7-449F-96AB-F58F34D03A7A}.z3apidebug|x86.Build.0 = z3apidebug|x86
{435D5BD0-6F62-49F8-BB24-33E2257519AD}.Checked|.NET.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
@@ -105,6 +106,7 @@ Global {435D5BD0-6F62-49F8-BB24-33E2257519AD}.z3apidebug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{435D5BD0-6F62-49F8-BB24-33E2257519AD}.z3apidebug|Mixed Platforms.Build.0 = Debug|Any CPU
{435D5BD0-6F62-49F8-BB24-33E2257519AD}.z3apidebug|x86.ActiveCfg = z3apidebug|Any CPU
+ {435D5BD0-6F62-49F8-BB24-33E2257519AD}.z3apidebug|x86.Build.0 = z3apidebug|Any CPU
{0EFA3E43-690B-48DC-A72C-384A3EA7F31F}.Checked|.NET.ActiveCfg = Checked|Any CPU
{0EFA3E43-690B-48DC-A72C-384A3EA7F31F}.Checked|Any CPU.ActiveCfg = Checked|Any CPU
{0EFA3E43-690B-48DC-A72C-384A3EA7F31F}.Checked|Any CPU.Build.0 = Checked|Any CPU
@@ -129,7 +131,8 @@ Global {0EFA3E43-690B-48DC-A72C-384A3EA7F31F}.z3apidebug|Any CPU.Build.0 = z3apidebug|Any CPU
{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
+ {0EFA3E43-690B-48DC-A72C-384A3EA7F31F}.z3apidebug|x86.ActiveCfg = z3apidebug|x86
+ {0EFA3E43-690B-48DC-A72C-384A3EA7F31F}.z3apidebug|x86.Build.0 = z3apidebug|x86
{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
@@ -155,6 +158,7 @@ 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
+ {9B163AA3-36BC-4AFB-88AB-79BC9E97E401}.z3apidebug|x86.Build.0 = 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
@@ -180,6 +184,7 @@ Global {E1F10180-C7B9-4147-B51F-FA1B701966DC}.z3apidebug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{E1F10180-C7B9-4147-B51F-FA1B701966DC}.z3apidebug|Mixed Platforms.Build.0 = Debug|Any CPU
{E1F10180-C7B9-4147-B51F-FA1B701966DC}.z3apidebug|x86.ActiveCfg = z3apidebug|Any CPU
+ {E1F10180-C7B9-4147-B51F-FA1B701966DC}.z3apidebug|x86.Build.0 = z3apidebug|Any CPU
{56FFDBCA-7D14-43B8-A6CA-22A20E417EE1}.Checked|.NET.ActiveCfg = Checked|Any CPU
{56FFDBCA-7D14-43B8-A6CA-22A20E417EE1}.Checked|Any CPU.ActiveCfg = Checked|Any CPU
{56FFDBCA-7D14-43B8-A6CA-22A20E417EE1}.Checked|Any CPU.Build.0 = Checked|Any CPU
@@ -204,6 +209,7 @@ Global {56FFDBCA-7D14-43B8-A6CA-22A20E417EE1}.z3apidebug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{56FFDBCA-7D14-43B8-A6CA-22A20E417EE1}.z3apidebug|Mixed Platforms.Build.0 = Debug|Any CPU
{56FFDBCA-7D14-43B8-A6CA-22A20E417EE1}.z3apidebug|x86.ActiveCfg = z3apidebug|Any CPU
+ {56FFDBCA-7D14-43B8-A6CA-22A20E417EE1}.z3apidebug|x86.Build.0 = z3apidebug|Any CPU
{B230A69C-C466-4065-B9C1-84D80E76D802}.Checked|.NET.ActiveCfg = Checked|Any CPU
{B230A69C-C466-4065-B9C1-84D80E76D802}.Checked|Any CPU.ActiveCfg = Checked|Any CPU
{B230A69C-C466-4065-B9C1-84D80E76D802}.Checked|Any CPU.Build.0 = Checked|Any CPU
@@ -228,6 +234,7 @@ Global {B230A69C-C466-4065-B9C1-84D80E76D802}.z3apidebug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{B230A69C-C466-4065-B9C1-84D80E76D802}.z3apidebug|Mixed Platforms.Build.0 = Debug|Any CPU
{B230A69C-C466-4065-B9C1-84D80E76D802}.z3apidebug|x86.ActiveCfg = z3apidebug|Any CPU
+ {B230A69C-C466-4065-B9C1-84D80E76D802}.z3apidebug|x86.Build.0 = z3apidebug|Any CPU
{966DD87B-A29D-4F3C-9406-F680A61DC0E0}.Checked|.NET.ActiveCfg = Checked|Any CPU
{966DD87B-A29D-4F3C-9406-F680A61DC0E0}.Checked|Any CPU.ActiveCfg = Checked|Any CPU
{966DD87B-A29D-4F3C-9406-F680A61DC0E0}.Checked|Any CPU.Build.0 = Checked|Any CPU
@@ -249,6 +256,7 @@ Global {966DD87B-A29D-4F3C-9406-F680A61DC0E0}.z3apidebug|Mixed Platforms.ActiveCfg = z3apidebug|Any CPU
{966DD87B-A29D-4F3C-9406-F680A61DC0E0}.z3apidebug|Mixed Platforms.Build.0 = z3apidebug|Any CPU
{966DD87B-A29D-4F3C-9406-F680A61DC0E0}.z3apidebug|x86.ActiveCfg = z3apidebug|Any CPU
+ {966DD87B-A29D-4F3C-9406-F680A61DC0E0}.z3apidebug|x86.Build.0 = z3apidebug|Any CPU
{39B0658D-C955-41C5-9A43-48C97A1EF5FD}.Checked|.NET.ActiveCfg = Checked|Any CPU
{39B0658D-C955-41C5-9A43-48C97A1EF5FD}.Checked|Any CPU.ActiveCfg = Checked|Any CPU
{39B0658D-C955-41C5-9A43-48C97A1EF5FD}.Checked|Any CPU.Build.0 = Checked|Any CPU
@@ -273,6 +281,7 @@ Global {39B0658D-C955-41C5-9A43-48C97A1EF5FD}.z3apidebug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{39B0658D-C955-41C5-9A43-48C97A1EF5FD}.z3apidebug|Mixed Platforms.Build.0 = Debug|Any CPU
{39B0658D-C955-41C5-9A43-48C97A1EF5FD}.z3apidebug|x86.ActiveCfg = z3apidebug|Any CPU
+ {39B0658D-C955-41C5-9A43-48C97A1EF5FD}.z3apidebug|x86.Build.0 = z3apidebug|Any CPU
{69A2B0B8-BCAC-4101-AE7A-556FCC58C06E}.Checked|.NET.ActiveCfg = Checked|Any CPU
{69A2B0B8-BCAC-4101-AE7A-556FCC58C06E}.Checked|Any CPU.ActiveCfg = Checked|Any CPU
{69A2B0B8-BCAC-4101-AE7A-556FCC58C06E}.Checked|Any CPU.Build.0 = Checked|Any CPU
@@ -297,6 +306,7 @@ Global {69A2B0B8-BCAC-4101-AE7A-556FCC58C06E}.z3apidebug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{69A2B0B8-BCAC-4101-AE7A-556FCC58C06E}.z3apidebug|Mixed Platforms.Build.0 = Debug|Any CPU
{69A2B0B8-BCAC-4101-AE7A-556FCC58C06E}.z3apidebug|x86.ActiveCfg = z3apidebug|Any CPU
+ {69A2B0B8-BCAC-4101-AE7A-556FCC58C06E}.z3apidebug|x86.Build.0 = z3apidebug|Any CPU
{43DFAD18-3E35-4558-9BE2-CAFF6B5BA8A0}.Checked|.NET.ActiveCfg = Checked|Any CPU
{43DFAD18-3E35-4558-9BE2-CAFF6B5BA8A0}.Checked|Any CPU.ActiveCfg = Checked|Any CPU
{43DFAD18-3E35-4558-9BE2-CAFF6B5BA8A0}.Checked|Any CPU.Build.0 = Checked|Any CPU
@@ -321,6 +331,7 @@ Global {43DFAD18-3E35-4558-9BE2-CAFF6B5BA8A0}.z3apidebug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{43DFAD18-3E35-4558-9BE2-CAFF6B5BA8A0}.z3apidebug|Mixed Platforms.Build.0 = Debug|Any CPU
{43DFAD18-3E35-4558-9BE2-CAFF6B5BA8A0}.z3apidebug|x86.ActiveCfg = z3apidebug|Any CPU
+ {43DFAD18-3E35-4558-9BE2-CAFF6B5BA8A0}.z3apidebug|x86.Build.0 = z3apidebug|Any CPU
{ACCC0156-0921-43ED-8F67-AD8BDC8CDE31}.Checked|.NET.ActiveCfg = Checked|Any CPU
{ACCC0156-0921-43ED-8F67-AD8BDC8CDE31}.Checked|Any CPU.ActiveCfg = Checked|Any CPU
{ACCC0156-0921-43ED-8F67-AD8BDC8CDE31}.Checked|Any CPU.Build.0 = Checked|Any CPU
@@ -345,6 +356,7 @@ Global {ACCC0156-0921-43ED-8F67-AD8BDC8CDE31}.z3apidebug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{ACCC0156-0921-43ED-8F67-AD8BDC8CDE31}.z3apidebug|Mixed Platforms.Build.0 = Debug|Any CPU
{ACCC0156-0921-43ED-8F67-AD8BDC8CDE31}.z3apidebug|x86.ActiveCfg = z3apidebug|Any CPU
+ {ACCC0156-0921-43ED-8F67-AD8BDC8CDE31}.z3apidebug|x86.Build.0 = z3apidebug|Any CPU
{A678C6EB-B329-46A9-BBFC-7585F01ACD7C}.Checked|.NET.ActiveCfg = Checked|x86
{A678C6EB-B329-46A9-BBFC-7585F01ACD7C}.Checked|Any CPU.ActiveCfg = Checked|x86
{A678C6EB-B329-46A9-BBFC-7585F01ACD7C}.Checked|Mixed Platforms.ActiveCfg = Checked|x86
@@ -393,6 +405,7 @@ Global {ACEF88D5-DADD-46DA-BAE1-2144D63F4C83}.z3apidebug|Mixed Platforms.ActiveCfg = Release|Any CPU
{ACEF88D5-DADD-46DA-BAE1-2144D63F4C83}.z3apidebug|Mixed Platforms.Build.0 = Release|Any CPU
{ACEF88D5-DADD-46DA-BAE1-2144D63F4C83}.z3apidebug|x86.ActiveCfg = Release|Any CPU
+ {ACEF88D5-DADD-46DA-BAE1-2144D63F4C83}.z3apidebug|x86.Build.0 = Release|Any CPU
{FCD3AC7F-9DFD-46C8-AB1E-09F0B0F16DC5}.Checked|.NET.ActiveCfg = Checked|Any CPU
{FCD3AC7F-9DFD-46C8-AB1E-09F0B0F16DC5}.Checked|Any CPU.ActiveCfg = Checked|Any CPU
{FCD3AC7F-9DFD-46C8-AB1E-09F0B0F16DC5}.Checked|Any CPU.Build.0 = Checked|Any CPU
@@ -417,6 +430,7 @@ 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
+ {FCD3AC7F-9DFD-46C8-AB1E-09F0B0F16DC5}.z3apidebug|x86.Build.0 = 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
@@ -441,6 +455,7 @@ Global {CF41E903-78EB-43BA-A355-E5FEB5ECECD4}.z3apidebug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{CF41E903-78EB-43BA-A355-E5FEB5ECECD4}.z3apidebug|Mixed Platforms.Build.0 = Debug|Any CPU
{CF41E903-78EB-43BA-A355-E5FEB5ECECD4}.z3apidebug|x86.ActiveCfg = Release|Any CPU
+ {CF41E903-78EB-43BA-A355-E5FEB5ECECD4}.z3apidebug|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/Source/BoogieDriver/BoogieDriver.cs b/Source/BoogieDriver/BoogieDriver.cs index 44adce15..ae26d8db 100644 --- a/Source/BoogieDriver/BoogieDriver.cs +++ b/Source/BoogieDriver/BoogieDriver.cs @@ -18,6 +18,7 @@ namespace Microsoft.Boogie { using Microsoft.Boogie.AbstractInterpretation;
using System.Diagnostics.Contracts;
using System.Diagnostics;
+ using System.Linq;
using VC;
using AI = Microsoft.AbstractInterpretationFramework;
using BoogiePL = Microsoft.Boogie;
@@ -178,6 +179,14 @@ namespace Microsoft.Boogie { return;
}
+ if (CommandLineOptions.Clo.PrintCFGPrefix != null) {
+ foreach (var impl in program.TopLevelDeclarations.OfType<Implementation>()) {
+ using (StreamWriter sw = new StreamWriter(CommandLineOptions.Clo.PrintCFGPrefix + "." + impl.Name + ".dot")) {
+ sw.Write(program.ProcessLoops(impl).ToDot());
+ }
+ }
+ }
+
EliminateDeadVariablesAndInline(program);
int errorCount, verified, inconclusives, timeOuts, outOfMemories;
diff --git a/Source/BoogieDriver/BoogieDriver.csproj b/Source/BoogieDriver/BoogieDriver.csproj index 9b6e329b..57aeb4d9 100644 --- a/Source/BoogieDriver/BoogieDriver.csproj +++ b/Source/BoogieDriver/BoogieDriver.csproj @@ -86,10 +86,10 @@ </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'z3apidebug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
- <OutputPath>bin\z3apidebug\</OutputPath>
+ <OutputPath>..\Provers\Z3api\bin\z3apidebug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
- <PlatformTarget>AnyCPU</PlatformTarget>
+ <PlatformTarget>x86</PlatformTarget>
<CodeAnalysisRuleAssemblies>
</CodeAnalysisRuleAssemblies>
<CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
@@ -138,6 +138,68 @@ <CodeContractsReferenceAssembly>Build</CodeContractsReferenceAssembly>
<CodeContractsAnalysisWarningLevel>0</CodeContractsAnalysisWarningLevel>
</PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\x86\Debug\</OutputPath>
+ <DefineConstants>TRACE;DEBUG</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>x86</PlatformTarget>
+ <CodeAnalysisLogFile>..\..\Binaries\Boogie.exe.CodeAnalysisLog.xml</CodeAnalysisLogFile>
+ <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
+ <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
+ <CodeAnalysisIgnoreBuiltInRuleSets>false</CodeAnalysisIgnoreBuiltInRuleSets>
+ <CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
+ <OutputPath>bin\x86\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <Optimize>true</Optimize>
+ <DebugType>pdbonly</DebugType>
+ <PlatformTarget>x86</PlatformTarget>
+ <CodeAnalysisLogFile>bin\Release\Boogie.exe.CodeAnalysisLog.xml</CodeAnalysisLogFile>
+ <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
+ <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
+ <CodeAnalysisIgnoreBuiltInRuleSets>false</CodeAnalysisIgnoreBuiltInRuleSets>
+ <CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
+ <CodeAnalysisIgnoreBuiltInRules>false</CodeAnalysisIgnoreBuiltInRules>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'z3apidebug|x86'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\x86\z3apidebug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>x86</PlatformTarget>
+ <CodeAnalysisLogFile>bin\z3apidebug\Boogie.exe.CodeAnalysisLog.xml</CodeAnalysisLogFile>
+ <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
+ <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>Migrated rules for BoogieDriver.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
+ <CodeAnalysisIgnoreBuiltInRuleSets>false</CodeAnalysisIgnoreBuiltInRuleSets>
+ <CodeAnalysisIgnoreBuiltInRules>true</CodeAnalysisIgnoreBuiltInRules>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Checked|x86'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\x86\Checked\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>x86</PlatformTarget>
+ <CodeAnalysisLogFile>..\..\Binaries\Boogie.exe.CodeAnalysisLog.xml</CodeAnalysisLogFile>
+ <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
+ <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
+ <CodeAnalysisIgnoreBuiltInRuleSets>false</CodeAnalysisIgnoreBuiltInRuleSets>
+ <CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
+ <CodeAnalysisIgnoreBuiltInRules>false</CodeAnalysisIgnoreBuiltInRules>
+ </PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Data" />
diff --git a/Source/Core/Absy.cs b/Source/Core/Absy.cs index 148a739d..c4b5d7a9 100644 --- a/Source/Core/Absy.cs +++ b/Source/Core/Absy.cs @@ -545,6 +545,8 @@ namespace Microsoft.Boogie { // header_last block that was created because of splitting header.
Dictionary<Block, Block> newBlocksCreated = new Dictionary<Block, Block>();
+ bool headRecursion = false; // testing an option to put recursive call before loop body
+
IEnumerable<Block> sortedHeaders = g.SortHeadersByDominance();
foreach (Block/*!*/ header in sortedHeaders)
{
@@ -565,7 +567,17 @@ namespace Microsoft.Boogie { continue;
Block newBlock = new Block();
newBlock.Label = block.Label;
- newBlock.Cmds = codeCopier.CopyCmdSeq(block.Cmds);
+ if (headRecursion && block == header)
+ {
+ CallCmd callCmd = (CallCmd)(loopHeaderToCallCmd2[header]).Clone();
+ addUniqueCallAttr(si_unique_loc, callCmd);
+ si_unique_loc++;
+ newBlock.Cmds.Add(callCmd); // add the recursive call at head of loop
+ var rest = codeCopier.CopyCmdSeq(block.Cmds);
+ newBlock.Cmds.AddRange(rest);
+ }
+ else
+ newBlock.Cmds = codeCopier.CopyCmdSeq(block.Cmds);
blockMap[block] = newBlock;
if (newBlocksCreated.ContainsKey(block))
{
@@ -616,14 +628,21 @@ namespace Microsoft.Boogie { }
}
- CallCmd callCmd = (CallCmd) (loopHeaderToCallCmd2[header]).Clone();
- addUniqueCallAttr(si_unique_loc, callCmd);
- si_unique_loc++;
+ CmdSeq cmdSeq;
+ if (headRecursion)
+ cmdSeq = new CmdSeq();
+ else
+ {
+ CallCmd callCmd = (CallCmd)(loopHeaderToCallCmd2[header]).Clone();
+ addUniqueCallAttr(si_unique_loc, callCmd);
+ si_unique_loc++;
+ cmdSeq = new CmdSeq(callCmd);
+ }
Block/*!*/ block1 = new Block(Token.NoToken, source.Label + "_dummy",
new CmdSeq(new AssumeCmd(Token.NoToken, Expr.False)), new ReturnCmd(Token.NoToken));
Block/*!*/ block2 = new Block(Token.NoToken, block1.Label,
- new CmdSeq(callCmd), new ReturnCmd(Token.NoToken));
+ cmdSeq, new ReturnCmd(Token.NoToken));
impl.Blocks.Add(block1);
dummyBlocks.Add(block1.Label);
@@ -2038,6 +2057,11 @@ namespace Microsoft.Boogie { }
}
+ public class Macro : Function {
+ public Macro(IToken tok, string name, VariableSeq args, Variable result)
+ : base(tok, name, args, result) { }
+ }
+
public class Requires : Absy, IPotentialErrorNode {
public readonly bool Free;
public Expr/*!*/ Condition;
diff --git a/Source/Core/CommandLineOptions.cs b/Source/Core/CommandLineOptions.cs index c28d8c8a..7d55e177 100644 --- a/Source/Core/CommandLineOptions.cs +++ b/Source/Core/CommandLineOptions.cs @@ -450,6 +450,7 @@ namespace Microsoft.Boogie { public string PrintErrorModelFile = null;
public string/*?*/ ModelViewFile = null;
public int EnhancedErrorMessages = 0;
+ public string PrintCFGPrefix = null;
public bool ForceBplErrors = false; // if true, boogie error is shown even if "msg" attribute is present
public bool UseArrayTheory = false;
public bool UseLabels = true;
@@ -834,6 +835,12 @@ namespace Microsoft.Boogie { ps.GetNumericArgument(ref EnhancedErrorMessages, 2);
return true;
+ case "printCFG":
+ if (ps.ConfirmArgumentCount(1)) {
+ PrintCFGPrefix = args[ps.i];
+ }
+ return true;
+
case "inlineDepth":
ps.GetNumericArgument(ref InlineDepth);
return true;
@@ -1449,6 +1456,10 @@ namespace Microsoft.Boogie { 0 (default) - no enhanced error messages
1 - Z3 error model enhanced error messages
+ /printCFG:<prefix> : print control flow graph of each implementation in
+ Graphviz format to files named:
+ <prefix>.<procedure name>.dot
+
---- Inference options -----------------------------------------------------
/infer:<flags>
diff --git a/Source/Core/Inline.cs b/Source/Core/Inline.cs index 88512025..63103399 100644 --- a/Source/Core/Inline.cs +++ b/Source/Core/Inline.cs @@ -384,7 +384,7 @@ namespace Microsoft.Boogie { codeCopier.OldSubst = null;
}
- private Cmd InlinedRequires(Implementation impl, CallCmd callCmd, Requires req) {
+ private Cmd InlinedRequires(CallCmd callCmd, Requires req) {
Requires/*!*/ reqCopy = (Requires/*!*/)cce.NonNull(req.Clone());
if (req.Free)
reqCopy.Condition = Expr.True;
@@ -395,16 +395,16 @@ namespace Microsoft.Boogie { return a;
}
- private Cmd InlinedEnsures(Implementation impl, CallCmd callCmd, Ensures ens) {
- if (impl.FindExprAttribute("inline") != null && !ens.Free) {
+ private Cmd InlinedEnsures(CallCmd callCmd, Ensures ens) {
+ if (QKeyValue.FindBoolAttribute(ens.Attributes, "assume")) {
+ return new AssumeCmd(ens.tok, codeCopier.CopyExpr(ens.Condition));
+ } else if (ens.Free) {
+ return new AssumeCmd(ens.tok, Expr.True);
+ } else {
Ensures/*!*/ ensCopy = (Ensures/*!*/)cce.NonNull(ens.Clone());
ensCopy.Condition = codeCopier.CopyExpr(ens.Condition);
return new AssertEnsuresCmd(ensCopy);
}
- else {
- //return new AssumeCmd(ens.tok, codeCopier.CopyExpr(ens.Condition));
- return new AssumeCmd(ens.tok, Expr.True);
- }
}
private CmdSeq RemoveAsserts(CmdSeq cmds) {
@@ -449,7 +449,7 @@ namespace Microsoft.Boogie { // inject requires
for (int i = 0; i < proc.Requires.Length; i++) {
Requires/*!*/ req = cce.NonNull(proc.Requires[i]);
- inCmds.Add(InlinedRequires(impl, callCmd, req));
+ inCmds.Add(InlinedRequires(callCmd, req));
}
VariableSeq locVars = cce.NonNull(impl.OriginalLocVars);
@@ -510,7 +510,7 @@ namespace Microsoft.Boogie { // inject ensures
for (int i = 0; i < proc.Ensures.Length; i++) {
Ensures/*!*/ ens = cce.NonNull(proc.Ensures[i]);
- outCmds.Add(InlinedEnsures(impl, callCmd, ens));
+ outCmds.Add(InlinedEnsures(callCmd, ens));
}
// assign out params
diff --git a/Source/Core/Util.cs b/Source/Core/Util.cs index f45e2995..a8e12f63 100644 --- a/Source/Core/Util.cs +++ b/Source/Core/Util.cs @@ -61,6 +61,11 @@ namespace Microsoft.Boogie { {
foreach (var e in coll) fn(e);
}
+
+ public static IEnumerable<Tuple<TSource1, TSource2>> Zip<TSource1, TSource2>(this IEnumerable<TSource1> source1, IEnumerable<TSource2> source2)
+ {
+ return source1.Zip(source2, (e1, e2) => new Tuple<TSource1, TSource2>(e1, e2));
+ }
}
public class TokenTextWriter : IDisposable {
diff --git a/Source/Dafny/Compiler.cs b/Source/Dafny/Compiler.cs index afab0c1f..fa8ea6da 100644 --- a/Source/Dafny/Compiler.cs +++ b/Source/Dafny/Compiler.cs @@ -74,18 +74,18 @@ namespace Microsoft.Dafny { }
int indent = 0;
if (!m.IsDefaultModule) {
- wr.WriteLine("namespace @{0} {{", m.Name);
+ wr.WriteLine("namespace @{0} {{", m.CompileName);
indent += IndentAmount;
}
foreach (TopLevelDecl d in m.TopLevelDecls) {
wr.WriteLine();
if (d is ArbitraryTypeDecl) {
var at = (ArbitraryTypeDecl)d;
- Error("Arbitrary type ('{0}') cannot be compiled", at.Name);
+ Error("Arbitrary type ('{0}') cannot be compiled", at.CompileName);
} else if (d is DatatypeDecl) {
var dt = (DatatypeDecl)d;
Indent(indent);
- wr.Write("public abstract class Base_{0}", dt.Name);
+ wr.Write("public abstract class Base_{0}", dt.CompileName);
if (dt.TypeArgs.Count != 0) {
wr.Write("<{0}>", TypeParameters(dt.TypeArgs));
}
@@ -95,7 +95,7 @@ namespace Microsoft.Dafny { } else {
ClassDecl cl = (ClassDecl)d;
Indent(indent);
- wr.Write("public class @{0}", cl.Name);
+ wr.Write("public class @{0}", cl.CompileName);
if (cl.TypeArgs.Count != 0) {
wr.Write("<{0}>", TypeParameters(cl.TypeArgs));
}
@@ -105,7 +105,7 @@ namespace Microsoft.Dafny { }
}
if (!m.IsDefaultModule) {
- wr.WriteLine("}} // end of namespace {0}", m.Name);
+ wr.WriteLine("}} // end of namespace {0}", m.CompileName);
}
}
}
@@ -200,18 +200,18 @@ namespace Microsoft.Dafny { // public Base_Dt<T> Get() { return c(); }
// }
Indent(indent);
- wr.WriteLine("public class {0}__Lazy{1} : Base_{0}{1} {{", dt.Name, typeParams);
+ wr.WriteLine("public class {0}__Lazy{1} : Base_{0}{1} {{", dt.CompileName, typeParams);
int ind = indent + IndentAmount;
Indent(ind);
- wr.WriteLine("public delegate Base_{0}{1} Computer();", dt.Name, typeParams);
+ wr.WriteLine("public delegate Base_{0}{1} Computer();", dt.CompileName, typeParams);
Indent(ind);
wr.WriteLine("public delegate Computer ComputerComputer();");
Indent(ind);
wr.WriteLine("Computer c;");
Indent(ind);
- wr.WriteLine("public {0}__Lazy(Computer c) {{ this.c = c; }}", dt.Name);
+ wr.WriteLine("public {0}__Lazy(Computer c) {{ this.c = c; }}", dt.CompileName);
Indent(ind);
- wr.WriteLine("public Base_{0}{1} Get() {{ return c(); }}", dt.Name, typeParams);
+ wr.WriteLine("public Base_{0}{1} Get() {{ return c(); }}", dt.CompileName, typeParams);
Indent(indent);
wr.WriteLine("}");
}
@@ -235,7 +235,7 @@ namespace Microsoft.Dafny { // }
Indent(indent);
wr.Write("public class {0}", DtCtorName(ctor, dt.TypeArgs));
- wr.WriteLine(" : Base_{0}{1} {{", dt.Name, typeParams);
+ wr.WriteLine(" : Base_{0}{1} {{", dt.CompileName, typeParams);
int ind = indent + IndentAmount;
int i = 0;
@@ -290,7 +290,7 @@ namespace Microsoft.Dafny { if (dt is IndDatatypeDecl) {
Indent(ind); wr.WriteLine("public override string ToString() {");
- string nm = (dt.Module.IsDefaultModule ? "" : dt.Module.Name + ".") + dt.Name + "." + ctor.Name;
+ string nm = (dt.Module.IsDefaultModule ? "" : dt.Module.CompileName + ".") + dt.CompileName + "." + ctor.CompileName;
Indent(ind + IndentAmount); wr.WriteLine("string s = \"{0}\";", nm);
if (ctor.Formals.Count != 0) {
Indent(ind + IndentAmount); wr.WriteLine("s += \"(\";");
@@ -345,13 +345,13 @@ namespace Microsoft.Dafny { // public override int GetHashCode() { return _D.GetHashCode(); }
// public override string ToString() { return _D.ToString(); } // only for inductive datatypes
//
- // public bool _Ctor0 { get { return _D is Dt_Ctor0; } }
+ // public bool is_Ctor0 { get { return _D is Dt_Ctor0; } }
// ...
//
// public T0 dtor_Dtor0 { get { return ((DT_Ctor)_D).@Dtor0; } }
// ...
// }
- string DtT = dt.Name;
+ string DtT = dt.CompileName;
string DtT_TypeArgs = "";
if (dt.TypeArgs.Count != 0) {
DtT_TypeArgs = "<" + TypeParameters(dt.TypeArgs) + ">";
@@ -376,9 +376,9 @@ namespace Microsoft.Dafny { if (dt is CoDatatypeDecl) {
string typeParams = dt.TypeArgs.Count == 0 ? "" : string.Format("<{0}>", TypeParameters(dt.TypeArgs));
Indent(ind + 2 * IndentAmount);
- wr.WriteLine("}} else if (d is {0}__Lazy{1}) {{", dt.Name, typeParams);
+ wr.WriteLine("}} else if (d is {0}__Lazy{1}) {{", dt.CompileName, typeParams);
Indent(ind + 3 * IndentAmount);
- wr.WriteLine("d = (({0}__Lazy{1})d).Get();", dt.Name, typeParams);
+ wr.WriteLine("d = (({0}__Lazy{1})d).Get();", dt.CompileName, typeParams);
}
Indent(ind + 2 * IndentAmount); wr.WriteLine("}");
Indent(ind + 2 * IndentAmount); wr.WriteLine("return d;");
@@ -386,7 +386,7 @@ namespace Microsoft.Dafny { Indent(ind); wr.WriteLine("}");
Indent(ind);
- wr.WriteLine("public @{0}(Base_{1} d) {{ this.d = d; }}", dt.Name, DtT);
+ wr.WriteLine("public @{0}(Base_{1} d) {{ this.d = d; }}", dt.CompileName, DtT);
Indent(ind);
wr.WriteLine("static Base_{0} theDefault;", DtT);
@@ -440,9 +440,9 @@ namespace Microsoft.Dafny { // query properties
foreach (var ctor in dt.Ctors) {
- // public bool _Ctor0 { get { return _D is Dt_Ctor0; } }
+ // public bool is_Ctor0 { get { return _D is Dt_Ctor0; } }
Indent(ind);
- wr.WriteLine("public bool _{0} {{ get {{ return _D is {1}_{0}{2}; }} }}", ctor.Name, dt.Name, DtT_TypeArgs);
+ wr.WriteLine("public bool is_{0} {{ get {{ return _D is {1}_{0}{2}; }} }}", ctor.CompileName, dt.CompileName, DtT_TypeArgs);
}
// destructors
@@ -451,7 +451,7 @@ namespace Microsoft.Dafny { if (!arg.IsGhost && arg.HasName) {
// public T0 @Dtor0 { get { return ((DT_Ctor)_D).@Dtor0; } }
Indent(ind);
- wr.WriteLine("public {0} dtor_{1} {{ get {{ return (({2}_{3}{4})_D).@{1}; }} }}", TypeName(arg.Type), arg.Name, dt.Name, ctor.Name, DtT_TypeArgs);
+ wr.WriteLine("public {0} dtor_{1} {{ get {{ return (({2}_{3}{4})_D).@{1}; }} }}", TypeName(arg.Type), arg.CompileName, dt.CompileName, ctor.CompileName, DtT_TypeArgs);
}
}
}
@@ -480,14 +480,14 @@ namespace Microsoft.Dafny { Contract.Requires(formal != null);
Contract.Ensures(Contract.Result<string>() != null);
- return formal.HasName ? formal.Name : "_a" + i;
+ return formal.HasName ? formal.CompileName : "_a" + i;
}
string DtCtorName(DatatypeCtor ctor) {
Contract.Requires(ctor != null);
Contract.Ensures(Contract.Result<string>() != null);
- return cce.NonNull(ctor.EnclosingDatatype).Name + "_" + ctor.Name;
+ return cce.NonNull(ctor.EnclosingDatatype).CompileName + "_" + ctor.CompileName;
}
string DtCtorName(DatatypeCtor ctor, List<TypeParameter> typeParams) {
@@ -539,7 +539,7 @@ namespace Microsoft.Dafny { Field f = (Field)member;
if (!f.IsGhost) {
Indent(indent);
- wr.WriteLine("public {0} @{1} = {2};", TypeName(f.Type), f.Name, DefaultValue(f.Type));
+ wr.WriteLine("public {0} @{1} = {2};", TypeName(f.Type), f.CompileName, DefaultValue(f.Type));
}
} else if (member is Function) {
@@ -550,7 +550,7 @@ namespace Microsoft.Dafny { Error("Function {0} has no body", f.FullName);
} else {
Indent(indent);
- wr.Write("public {0}{1} @{2}", f.IsStatic ? "static " : "", TypeName(f.ResultType), f.Name);
+ wr.Write("public {0}{1} @{2}", f.IsStatic ? "static " : "", TypeName(f.ResultType), f.CompileName);
if (f.TypeArgs.Count != 0) {
wr.Write("<{0}>", TypeParameters(f.TypeArgs));
}
@@ -565,7 +565,7 @@ namespace Microsoft.Dafny { Method m = (Method)member;
if (!m.IsGhost) {
Indent(indent);
- wr.Write("public {0}void @{1}", m.IsStatic ? "static " : "", m.Name);
+ wr.Write("public {0}void @{1}", m.IsStatic ? "static " : "", m.CompileName);
if (m.TypeArgs.Count != 0) {
wr.Write("<{0}>", TypeParameters(m.TypeArgs));
}
@@ -579,7 +579,7 @@ namespace Microsoft.Dafny { foreach (Formal p in m.Outs) {
if (!p.IsGhost) {
Indent(indent + IndentAmount);
- wr.WriteLine("@{0} = {1};", p.Name, DefaultValue(p.Type));
+ wr.WriteLine("@{0} = {1};", p.CompileName, DefaultValue(p.Type));
}
}
if (m.Body == null) {
@@ -595,7 +595,7 @@ namespace Microsoft.Dafny { wr.WriteLine("public static void Main(string[] args) {");
Contract.Assert(m.EnclosingClass == c);
Indent(indent + IndentAmount);
- wr.Write("@{0} b = new @{0}", c.Name);
+ wr.Write("@{0} b = new @{0}", c.CompileName);
if (c.TypeArgs.Count != 0) {
// instantiate every parameter, it doesn't particularly matter how
wr.Write("<");
@@ -623,7 +623,7 @@ namespace Microsoft.Dafny { if (body is MatchExpr) {
MatchExpr me = (MatchExpr)body;
// Type source = e;
- // if (source._Ctor0) {
+ // if (source.is_Ctor0) {
// FormalType f0 = ((Dt_Ctor0)source._D).a0;
// ...
// return Body0;
@@ -675,7 +675,7 @@ namespace Microsoft.Dafny { var e = (LetExpr)expr;
foreach (var v in e.Vars) {
Indent(indent);
- wr.WriteLine("{0} @{1};", TypeName(v.Type), v.Name);
+ wr.WriteLine("{0} @{1};", TypeName(v.Type), v.CompileName);
}
}
foreach (var ee in expr.SubExpressions) {
@@ -724,7 +724,7 @@ namespace Microsoft.Dafny { return name + "]";
} else if (type is UserDefinedType) {
UserDefinedType udt = (UserDefinedType)type;
- string s = "@" + udt.FullName;
+ string s = "@" + udt.FullCompileName;
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");
@@ -782,7 +782,7 @@ namespace Microsoft.Dafny { string s = "";
string sep = "";
foreach (TypeParameter tp in targs) {
- s += sep + "@" + tp.Name;
+ s += sep + "@" + tp.CompileName;
sep = ",";
}
return s;
@@ -813,14 +813,14 @@ namespace Microsoft.Dafny { return string.Format("({0})null", TypeName(type));
} else if (type.IsDatatype) {
UserDefinedType udt = (UserDefinedType)type;
- string s = "@" + udt.Name;
+ string s = "@" + udt.FullCompileName;
if (udt.TypeArgs.Count != 0) {
s += "<" + TypeNames(udt.TypeArgs) + ">";
}
return string.Format("new {0}()", s);
} else if (type.IsTypeParameter) {
UserDefinedType udt = (UserDefinedType)type;
- return "default(@" + udt.Name + ")";
+ return "default(@" + udt.FullCompileName + ")";
} else if (type is SetType) {
return DafnySetClass + "<" + TypeName(((SetType)type).Arg) + ">.Empty";
} else if (type is MultiSetType) {
@@ -841,7 +841,10 @@ namespace Microsoft.Dafny { if (stmt is AssumeStmt) {
Error("an assume statement cannot be compiled (line {0})", stmt.Tok.line);
} else if (stmt is AssignSuchThatStmt) {
- Error("an assign-such-that statement cannot be compiled (line {0})", stmt.Tok.line);
+ var s = (AssignSuchThatStmt)stmt;
+ if (s.AssumeToken != null) {
+ Error("an assume statement cannot be compiled (line {0})", s.AssumeToken.line);
+ }
} else {
foreach (var ss in stmt.SubStatements) {
CheckHasNoAssumes(ss);
@@ -882,7 +885,7 @@ namespace Microsoft.Dafny { } else if (stmt is BreakStmt) {
var s = (BreakStmt)stmt;
Indent(indent);
- wr.WriteLine("goto after_{0};", s.TargetStmt.Labels.UniqueId);
+ wr.WriteLine("goto after_{0};", s.TargetStmt.Labels.Data.UniqueId);
} else if (stmt is ReturnStmt) {
var s = (ReturnStmt)stmt;
if (s.hiddenUpdate != null)
@@ -925,6 +928,16 @@ namespace Microsoft.Dafny { Contract.Assert(!(s.Lhs is SeqSelectExpr) || ((SeqSelectExpr)s.Lhs).SelectOne); // multi-element array assignments are not allowed
TrRhs(null, s.Lhs, s.Rhs, indent);
+ } else if (stmt is AssignSuchThatStmt) {
+ var s = (AssignSuchThatStmt)stmt;
+ foreach (var lhs in s.Lhss) {
+ // assigning to a local ghost variable or to a ghost field is okay
+ if (!AssignStmt.LhsIsToGhost(lhs)) {
+ Error("compiling an assign-such-that statement with a non-ghost left-hand side is currently not supported (line {0})", stmt.Tok.line);
+ break; // no need to say more
+ }
+ }
+
} else if (stmt is VarDecl) {
TrVarDecl((VarDecl)stmt, true, indent);
@@ -1099,7 +1112,7 @@ namespace Microsoft.Dafny { // declare and construct "ingredients"
Indent(indent);
- wr.WriteLine("var {0} = new List<System.Tuple<{1}>>();", ingredients, tupleTypeArgs);
+ wr.WriteLine("var {0} = new System.Collections.Generic.List<System.Tuple<{1}>>();", ingredients, tupleTypeArgs);
var n = s.BoundVars.Count;
Contract.Assert(s.Bounds.Count == n);
@@ -1109,29 +1122,29 @@ namespace Microsoft.Dafny { var bv = s.BoundVars[i];
if (bound is QuantifierExpr.BoolBoundedPool) {
Indent(ind);
- wr.Write("foreach (var @{0} in Dafny.Helpers.AllBooleans) {{ ", bv.Name);
+ wr.Write("foreach (var @{0} in Dafny.Helpers.AllBooleans) {{ ", bv.CompileName);
} else if (bound is QuantifierExpr.IntBoundedPool) {
var b = (QuantifierExpr.IntBoundedPool)bound;
SpillLetVariableDecls(b.LowerBound, ind);
SpillLetVariableDecls(b.UpperBound, ind);
Indent(ind);
- wr.Write("for (var @{0} = ", bv.Name);
+ wr.Write("for (var @{0} = ", bv.CompileName);
TrExpr(b.LowerBound);
- wr.Write("; @{0} < ", bv.Name);
+ wr.Write("; @{0} < ", bv.CompileName);
TrExpr(b.UpperBound);
- wr.Write("; @{0}++) {{ ", bv.Name);
+ wr.Write("; @{0}++) {{ ", bv.CompileName);
} else if (bound is QuantifierExpr.SetBoundedPool) {
var b = (QuantifierExpr.SetBoundedPool)bound;
SpillLetVariableDecls(b.Set, ind);
Indent(ind);
- wr.Write("foreach (var @{0} in (", bv.Name);
+ wr.Write("foreach (var @{0} in (", bv.CompileName);
TrExpr(b.Set);
wr.Write(").Elements) { ");
} else if (bound is QuantifierExpr.SeqBoundedPool) {
var b = (QuantifierExpr.SeqBoundedPool)bound;
SpillLetVariableDecls(b.Seq, ind);
Indent(ind);
- wr.Write("foreach (var @{0} in (", bv.Name);
+ wr.Write("foreach (var @{0} in (", bv.CompileName);
TrExpr(b.Seq);
wr.Write(").UniqueElements) { ");
} else {
@@ -1213,7 +1226,7 @@ namespace Microsoft.Dafny { } else if (stmt is MatchStmt) {
MatchStmt s = (MatchStmt)stmt;
// Type source = e;
- // if (source._Ctor0) {
+ // if (source.is_Ctor0) {
// FormalType f0 = ((Dt_Ctor0)source._D).a0;
// ...
// Body0;
@@ -1258,7 +1271,7 @@ namespace Microsoft.Dafny { SpillLetVariableDecls(lhs, indent);
if (lhs is IdentifierExpr) {
var ll = (IdentifierExpr)lhs;
- return "@" + ll.Var.Name;
+ return "@" + ll.Var.CompileName;
} else if (lhs is FieldSelectExpr) {
var ll = (FieldSelectExpr)lhs;
string obj = "_obj" + tmpVarCount;
@@ -1267,7 +1280,7 @@ namespace Microsoft.Dafny { wr.Write("var {0} = ", obj);
TrExpr(ll.Obj);
wr.WriteLine(";");
- return string.Format("{0}.@{1}", obj, ll.Field.Name);
+ return string.Format("{0}.@{1}", obj, ll.Field.CompileName);
} else if (lhs is SeqSelectExpr) {
var ll = (SeqSelectExpr)lhs;
string arr = "_arr" + tmpVarCount;
@@ -1390,7 +1403,7 @@ namespace Microsoft.Dafny { Indent(indent);
TrParenExpr(s.Receiver);
}
- wr.Write(".@{0}(", s.Method.Name);
+ wr.Write(".@{0}(", s.Method.CompileName);
string sep = "";
for (int i = 0; i < s.Method.Ins.Count; i++) {
@@ -1462,7 +1475,7 @@ namespace Microsoft.Dafny { TrStmt(ss, indent + IndentAmount);
if (ss.Labels != null) {
Indent(indent); // labels are not indented as much as the statements
- wr.WriteLine("after_{0}: ;", ss.Labels.UniqueId);
+ wr.WriteLine("after_{0}: ;", ss.Labels.Data.UniqueId);
}
}
}
@@ -1475,7 +1488,7 @@ namespace Microsoft.Dafny { }
Indent(indent);
- wr.Write("{0} @{1}", TypeName(s.Type), s.Name);
+ wr.Write("{0} @{1}", TypeName(s.Type), s.CompileName);
if (alwaysInitialize) {
// produce a default value
wr.WriteLine(" = {0};", DefaultValue(s.Type));
@@ -1489,7 +1502,7 @@ namespace Microsoft.Dafny { Contract.Requires(sourceType != null);
Contract.Requires(ctor != null);
Contract.Requires(cce.NonNullElements(arguments));
- // if (source._Ctor0) {
+ // if (source.is_Ctor0) {
// FormalType f0 = ((Dt_Ctor0)source._D).a0;
// ...
Indent(indent);
@@ -1497,7 +1510,7 @@ namespace Microsoft.Dafny { if (caseIndex == caseCount - 1) {
wr.Write("true");
} else {
- wr.Write("{0}._{1}", source, ctor.Name);
+ wr.Write("{0}.is_{1}", source, ctor.CompileName);
}
wr.WriteLine(") {");
@@ -1509,7 +1522,7 @@ namespace Microsoft.Dafny { // FormalType f0 = ((Dt_Ctor0)source._D).a0;
Indent(indent + IndentAmount);
wr.WriteLine("{0} @{1} = (({2}){3}._D).@{4};",
- TypeName(bv.Type), bv.Name, DtCtorName(ctor, sourceType.TypeArgs), source, FormalName(arg, k));
+ TypeName(bv.Type), bv.CompileName, DtCtorName(ctor, sourceType.TypeArgs), source, FormalName(arg, k));
k++;
}
}
@@ -1599,7 +1612,7 @@ namespace Microsoft.Dafny { } else if (expr is IdentifierExpr) {
IdentifierExpr e = (IdentifierExpr)expr;
- wr.Write("@" + e.Var.Name);
+ wr.Write("@" + e.Var.CompileName);
} else if (expr is SetDisplayExpr) {
SetDisplayExpr e = (SetDisplayExpr)expr;
@@ -1634,7 +1647,7 @@ namespace Microsoft.Dafny { wr.Write(sf.PostString);
} else {
TrParenExpr(e.Obj);
- wr.Write(".@{0}", e.Field.Name);
+ wr.Write(".@{0}", e.Field.CompileName);
}
} else if (expr is SeqSelectExpr) {
@@ -1800,7 +1813,7 @@ namespace Microsoft.Dafny { wr.Write(".Length)");
} else {
TrParenExpr(e.E);
- wr.Write(".Length");
+ wr.Write(".Length");
}
break;
default:
@@ -1827,6 +1840,11 @@ namespace Microsoft.Dafny { Type t = cce.NonNull(e.E0.Type);
if (t.IsDatatype || t.IsTypeParameter) {
callString = "Equals";
+ } else if (t.IsRefType) {
+ // Dafny's type rules are slightly different C#, so we may need a cast here.
+ // For example, Dafny allows x==y if x:array<T> and y:array<int> and T is some
+ // type parameter.
+ opString = "== (object)";
} else {
opString = "==";
}
@@ -1837,6 +1855,11 @@ namespace Microsoft.Dafny { if (t.IsDatatype || t.IsTypeParameter) {
preOpString = "!";
callString = "Equals";
+ } else if (t.IsRefType) {
+ // Dafny's type rules are slightly different C#, so we may need a cast here.
+ // For example, Dafny allows x==y if x:array<T> and y:array<int> and T is some
+ // type parameter.
+ opString = "!= (object)";
} else {
opString = "!=";
}
@@ -1969,7 +1992,7 @@ namespace Microsoft.Dafny { // preceded by the declaration of x.
Contract.Assert(e.Vars.Count == e.RHSs.Count); // checked by resolution
for (int i = 0; i < e.Vars.Count; i++) {
- wr.Write("Dafny.Helpers.ExpressionSequence(@{0} = ", e.Vars[i].Name);
+ wr.Write("Dafny.Helpers.ExpressionSequence(@{0} = ", e.Vars[i].CompileName);
TrExpr(e.RHSs[i]);
wr.Write(", ");
}
@@ -2015,7 +2038,7 @@ namespace Microsoft.Dafny { Contract.Assert(false); throw new cce.UnreachableException(); // unexpected BoundedPool type
}
wr.Write("{0}, ", expr is ForallExpr ? "true" : "false");
- wr.Write("@{0} => ", bv.Name);
+ wr.Write("@{0} => ", bv.CompileName);
}
TrExpr(e.LogicalBody());
for (int i = 0; i < n; i++) {
@@ -2050,27 +2073,27 @@ namespace Microsoft.Dafny { var bound = e.Bounds[i];
var bv = e.BoundVars[i];
if (bound is QuantifierExpr.BoolBoundedPool) {
- wr.Write("foreach (var @{0} in Dafny.Helpers.AllBooleans) {{ ", bv.Name);
+ wr.Write("foreach (var @{0} in Dafny.Helpers.AllBooleans) {{ ", bv.CompileName);
} else if (bound is QuantifierExpr.IntBoundedPool) {
var b = (QuantifierExpr.IntBoundedPool)bound;
- wr.Write("for (var @{0} = ", bv.Name);
+ wr.Write("for (var @{0} = ", bv.CompileName);
TrExpr(b.LowerBound);
- wr.Write("; @{0} < ", bv.Name);
+ wr.Write("; @{0} < ", bv.CompileName);
TrExpr(b.UpperBound);
- wr.Write("; @{0}++) {{ ", bv.Name);
+ wr.Write("; @{0}++) {{ ", bv.CompileName);
} else if (bound is QuantifierExpr.SetBoundedPool) {
var b = (QuantifierExpr.SetBoundedPool)bound;
- wr.Write("foreach (var @{0} in (", bv.Name);
+ wr.Write("foreach (var @{0} in (", bv.CompileName);
TrExpr(b.Set);
wr.Write(").Elements) { ");
} else if (bound is QuantifierExpr.MapBoundedPool) {
var b = (QuantifierExpr.MapBoundedPool)bound;
- wr.Write("foreach (var @{0} in (", bv.Name);
+ wr.Write("foreach (var @{0} in (", bv.CompileName);
TrExpr(b.Map);
wr.Write(").Domain) { ");
} else if (bound is QuantifierExpr.SeqBoundedPool) {
var b = (QuantifierExpr.SeqBoundedPool)bound;
- wr.Write("foreach (var @{0} in (", bv.Name);
+ wr.Write("foreach (var @{0} in (", bv.CompileName);
TrExpr(b.Seq);
wr.Write(").Elements) { ");
} else {
@@ -2116,27 +2139,27 @@ namespace Microsoft.Dafny { var bound = e.Bounds[0];
var bv = e.BoundVars[0];
if (bound is QuantifierExpr.BoolBoundedPool) {
- wr.Write("foreach (var @{0} in Dafny.Helpers.AllBooleans) {{ ", bv.Name);
+ wr.Write("foreach (var @{0} in Dafny.Helpers.AllBooleans) {{ ", bv.CompileName);
} else if (bound is QuantifierExpr.IntBoundedPool) {
var b = (QuantifierExpr.IntBoundedPool)bound;
- wr.Write("for (var @{0} = ", bv.Name);
+ wr.Write("for (var @{0} = ", bv.CompileName);
TrExpr(b.LowerBound);
- wr.Write("; @{0} < ", bv.Name);
+ wr.Write("; @{0} < ", bv.CompileName);
TrExpr(b.UpperBound);
- wr.Write("; @{0}++) {{ ", bv.Name);
+ wr.Write("; @{0}++) {{ ", bv.CompileName);
} else if (bound is QuantifierExpr.SetBoundedPool) {
var b = (QuantifierExpr.SetBoundedPool)bound;
- wr.Write("foreach (var @{0} in (", bv.Name);
+ wr.Write("foreach (var @{0} in (", bv.CompileName);
TrExpr(b.Set);
wr.Write(").Elements) { ");
} else if (bound is QuantifierExpr.MapBoundedPool) {
var b = (QuantifierExpr.MapBoundedPool)bound;
- wr.Write("foreach (var @{0} in (", bv.Name);
+ wr.Write("foreach (var @{0} in (", bv.CompileName);
TrExpr(b.Map);
wr.Write(").Domain) { ");
} else if (bound is QuantifierExpr.SeqBoundedPool) {
var b = (QuantifierExpr.SeqBoundedPool)bound;
- wr.Write("foreach (var @{0} in (", bv.Name);
+ wr.Write("foreach (var @{0} in (", bv.CompileName);
TrExpr(b.Seq);
wr.Write(").Elements) { ");
} else {
@@ -2145,7 +2168,7 @@ namespace Microsoft.Dafny { wr.Write("if (");
TrExpr(e.Range);
wr.Write(") { ");
- wr.Write("_coll.Add(new Dafny.Pair<{0},{1}>(@{2},", domtypeName, rantypeName, bv.Name);
+ wr.Write("_coll.Add(new Dafny.Pair<{0},{1}>(@{2},", domtypeName, rantypeName, bv.CompileName);
TrExpr(e.Term);
wr.Write(")); }");
wr.Write("}");
@@ -2186,7 +2209,7 @@ namespace Microsoft.Dafny { tr(e.Receiver);
twr.Write(")");
}
- twr.Write(".@{0}", f.Name);
+ twr.Write(".@{0}", f.CompileName);
twr.Write("(");
string sep = "";
for (int i = 0; i < e.Args.Count; i++) {
diff --git a/Source/Dafny/Dafny.atg b/Source/Dafny/Dafny.atg index 97da97e3..13f6c245 100644 --- a/Source/Dafny/Dafny.atg +++ b/Source/Dafny/Dafny.atg @@ -24,7 +24,6 @@ static int anonymousIds = 0; struct MemberModifiers {
public bool IsGhost;
public bool IsStatic;
- public bool IsUnlimited;
}
// helper routine for parsing call statements
///<summary>
@@ -226,7 +225,6 @@ ClassMemberDecl<.List<MemberDecl/*!*/>/*!*/ mm, bool isAlreadyGhost, bool allowC .)
{ "ghost" (. mmod.IsGhost = true; .)
| "static" (. mmod.IsStatic = true; .)
- | "unlimited" (. mmod.IsUnlimited = true; .)
}
( FieldDecl<mmod, mm>
| FunctionDecl<mmod, out f> (. mm.Add(f); .)
@@ -281,8 +279,7 @@ FieldDecl<.MemberModifiers mmod, List<MemberDecl/*!*/>/*!*/ mm.> .)
SYNC
"var"
- (. if (mmod.IsUnlimited) { SemErr(t, "fields cannot be declared 'unlimited'"); }
- if (mmod.IsStatic) { SemErr(t, "fields cannot be declared 'static'"); }
+ (. if (mmod.IsStatic) { SemErr(t, "fields cannot be declared 'static'"); }
.)
{ Attribute<ref attrs> }
IdentType<out id, out ty> (. mm.Add(new Field(id, id.val, mmod.IsGhost, ty, attrs)); .)
@@ -396,8 +393,7 @@ MethodDecl<MemberModifiers mmod, bool allowConstructor, out Method/*!*/ m> }
.)
)
- (. if (mmod.IsUnlimited) { SemErr(t, "methods cannot be declared 'unlimited'"); }
- if (isConstructor) {
+ (. if (isConstructor) {
if (mmod.IsGhost) {
SemErr(t, "constructors cannot be declared 'ghost'");
}
@@ -503,7 +499,7 @@ TypeAndToken<out IToken/*!*/ tok, out Type/*!*/ ty> GenericInstantiation<gt> (. if (gt.Count != 2) {
SemErr("map type expects exactly two type arguments");
}
- ty = new MapType(gt[0], gt[1]);
+ else { ty = new MapType(gt[0], gt[1]); }
.)
| ReferenceType<out tok, out ty>
)
@@ -511,6 +507,7 @@ TypeAndToken<out IToken/*!*/ tok, out Type/*!*/ ty> ReferenceType<out IToken/*!*/ tok, out Type/*!*/ ty>
= (. Contract.Ensures(Contract.ValueAtReturn(out tok) != null); Contract.Ensures(Contract.ValueAtReturn(out ty) != null);
tok = Token.NoToken; ty = new BoolType(); /*keep compiler happy*/
+ IToken moduleName = null;
List<Type/*!*/>/*!*/ gt;
.)
( "object" (. tok = t; ty = new ObjectType(); .)
@@ -525,7 +522,10 @@ ReferenceType<out IToken/*!*/ tok, out Type/*!*/ ty> ty = theBuiltIns.ArrayType(tok, dims, gt[0], true);
.)
| Ident<out tok> (. gt = new List<Type/*!*/>(); .)
- [ GenericInstantiation<gt> ] (. ty = new UserDefinedType(tok, tok.val, gt); .)
+ [ (. moduleName = tok; .)
+ "." Ident<out tok>
+ ]
+ [ GenericInstantiation<gt> ] (. ty = new UserDefinedType(tok, tok.val, gt, moduleName); .)
)
.
GenericInstantiation<.List<Type/*!*/>/*!*/ gt.>
@@ -596,10 +596,10 @@ FunctionDecl<MemberModifiers mmod, out Function/*!*/ f> [ FunctionBody<out body, out bodyStart, out bodyEnd>
]
(. if (isPredicate) {
- f = new Predicate(id, id.val, mmod.IsStatic, !isFunctionMethod, mmod.IsUnlimited, typeArgs, openParen, formals,
+ f = new Predicate(id, id.val, mmod.IsStatic, !isFunctionMethod, typeArgs, openParen, formals,
reqs, reads, ens, new Specification<Expression>(decreases, null), body, false, attrs, signatureOmitted);
} else {
- f = new Function(id, id.val, mmod.IsStatic, !isFunctionMethod, mmod.IsUnlimited, typeArgs, openParen, formals, returnType,
+ f = new Function(id, id.val, mmod.IsStatic, !isFunctionMethod, typeArgs, openParen, formals, returnType,
reqs, reads, ens, new Specification<Expression>(decreases, null), body, attrs, signatureOmitted);
}
f.BodyStartTok = bodyStart;
@@ -691,7 +691,7 @@ OneStmt<out Statement/*!*/ s> | ParallelStmt<out s>
| "label" (. x = t; .)
Ident<out id> ":"
- OneStmt<out s> (. s.Labels = new LabelNode(x, id.val, s.Labels); .)
+ OneStmt<out s> (. s.Labels = new LList<Label>(new Label(x, id.val), s.Labels); .)
| "break" (. x = t; breakCount = 1; label = null; .)
( Ident<out id> (. label = id.val; .)
| { "break" (. breakCount++; .)
@@ -725,6 +725,7 @@ UpdateStmt<out Statement/*!*/ s> Expression lhs0;
IToken x;
Attributes attrs = null;
+ IToken suchThatAssume = null;
Expression suchThat = null;
.)
Lhs<out e> (. x = e.tok; .)
@@ -738,13 +739,15 @@ UpdateStmt<out Statement/*!*/ s> { "," Rhs<out r, lhs0> (. rhss.Add(r); .)
}
| ":|" (. x = t; .)
+ [ "assume" (. suchThatAssume = t; .)
+ ]
Expression<out suchThat>
)
";"
| ":" (. SemErr(t, "invalid statement (did you forget the 'label' keyword?)"); .)
)
(. if (suchThat != null) {
- s = new AssignSuchThatStmt(x, lhss, suchThat);
+ s = new AssignSuchThatStmt(x, lhss, suchThat, suchThatAssume);
} else {
s = new UpdateStmt(x, lhss, rhss);
}
@@ -769,8 +772,23 @@ Rhs<out AssignmentRhs r, Expression receiverForInitCall> | "." Ident<out x>
"(" (. args = new List<Expression/*!*/>(); .)
[ Expressions<args> ]
- ")" (. initCall = new CallStmt(x, new List<Expression>(),
- receiverForInitCall, x.val, args); .)
+ ")" (. initCall = new CallStmt(x, new List<Expression>(), receiverForInitCall, x.val, args); .)
+ | "(" (. var udf = ty as UserDefinedType;
+ if (udf != null && udf.ModuleName != null && udf.TypeArgs.Count == 0) {
+ // The parsed name had the form "A.B", so treat "A" as the name of the type and "B" as
+ // the name of the constructor that's being invoked.
+ x = udf.tok;
+ ty = new UserDefinedType(udf.ModuleName, udf.ModuleName.val, new List<Type>(), null);
+ } else {
+ SemErr(t, "expected '.'");
+ x = null;
+ }
+ args = new List<Expression/*!*/>(); .)
+ [ Expressions<args> ]
+ ")" (. if (x != null) {
+ initCall = new CallStmt(x, new List<Expression>(), receiverForInitCall, x.val, args);
+ }
+ .)
]
(. if (ee != null) {
r = new TypeRhs(newToken, ty, ee);
@@ -784,7 +802,7 @@ Rhs<out AssignmentRhs r, Expression receiverForInitCall> | "*" (. r = new HavocRhs(t); .)
| Expression<out e> (. r = new ExprRhs(e); .)
)
- { Attribute<ref attrs> } (. r.Attributes = attrs; .)
+ { Attribute<ref attrs> } (. if (r != null) r.Attributes = attrs; .)
.
VarDeclStatement<.out Statement/*!*/ s.>
= (. IToken x = null, assignTok = null; bool isGhost = false;
@@ -792,6 +810,7 @@ VarDeclStatement<.out Statement/*!*/ s.> AssignmentRhs r; IdentifierExpr lhs0;
List<VarDecl> lhss = new List<VarDecl>();
List<AssignmentRhs> rhss = new List<AssignmentRhs>();
+ IToken suchThatAssume = null;
Expression suchThat = null;
.)
[ "ghost" (. isGhost = true; x = t; .)
@@ -809,6 +828,8 @@ VarDeclStatement<.out Statement/*!*/ s.> { "," Rhs<out r, lhs0> (. rhss.Add(r); .)
}
| ":|" (. assignTok = t; .)
+ [ "assume" (. suchThatAssume = t; .)
+ ]
Expression<out suchThat>
]
";"
@@ -818,7 +839,7 @@ VarDeclStatement<.out Statement/*!*/ s.> foreach (var lhs in lhss) {
ies.Add(new IdentifierExpr(lhs.Tok, lhs.Name));
}
- update = new AssignSuchThatStmt(assignTok, ies, suchThat);
+ update = new AssignSuchThatStmt(assignTok, ies, suchThat, suchThatAssume);
} else if (rhss.Count == 0) {
update = null;
} else {
diff --git a/Source/Dafny/DafnyAst.cs b/Source/Dafny/DafnyAst.cs index 5fd34e65..a57ef79d 100644 --- a/Source/Dafny/DafnyAst.cs +++ b/Source/Dafny/DafnyAst.cs @@ -54,7 +54,7 @@ namespace Microsoft.Dafny { List<Type/*!*/> typeArgs = new List<Type/*!*/>();
typeArgs.Add(arg);
- UserDefinedType udt = new UserDefinedType(tok, ArrayClassName(dims), typeArgs);
+ UserDefinedType udt = new UserDefinedType(tok, ArrayClassName(dims), typeArgs, null);
if (allowCreationOfNewClass && !arrayTypeDecls.ContainsKey(dims)) {
ArrayClassDecl arrayClass = new ArrayClassDecl(dims, SystemModule);
for (int d = 0; d < dims; d++) {
@@ -393,7 +393,8 @@ namespace Microsoft.Dafny { Contract.Invariant(cce.NonNullElements(TypeArgs));
}
- public readonly IToken tok;
+ public readonly IToken ModuleName; // may be null
+ public readonly IToken tok; // token of the Name
public readonly string Name;
[Rep]
public readonly List<Type/*!*/>/*!*/ TypeArgs;
@@ -408,13 +409,33 @@ namespace Microsoft.Dafny { }
}
+ string compileName;
+ public string CompileName {
+ get {
+ if (compileName == null) {
+ compileName = NonglobalVariable.CompilerizeName(Name);
+ }
+ return compileName;
+ }
+ }
+ public string FullCompileName {
+ get {
+ if (ResolvedClass != null && !ResolvedClass.Module.IsDefaultModule) {
+ return ResolvedClass.Module.CompileName + "." + CompileName;
+ } else {
+ return CompileName;
+ }
+ }
+ }
+
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
- public UserDefinedType(IToken/*!*/ tok, string/*!*/ name, [Captured] List<Type/*!*/>/*!*/ typeArgs) {
+ public UserDefinedType(IToken/*!*/ tok, string/*!*/ name, [Captured] List<Type/*!*/>/*!*/ typeArgs, IToken moduleName) {
Contract.Requires(tok != null);
Contract.Requires(name != null);
Contract.Requires(cce.NonNullElements(typeArgs));
+ this.ModuleName = moduleName;
this.tok = tok;
this.Name = name;
this.TypeArgs = typeArgs;
@@ -480,6 +501,9 @@ namespace Microsoft.Dafny { Contract.Ensures(Contract.Result<string>() != null);
string s = Name;
+ if (ModuleName != null) {
+ s = ModuleName.val + "." + s;
+ }
if (TypeArgs.Count != 0) {
string sep = "<";
foreach (Type t in TypeArgs) {
@@ -652,6 +676,15 @@ namespace Microsoft.Dafny { public IToken BodyStartTok = Token.NoToken;
public IToken BodyEndTok = Token.NoToken;
public readonly string/*!*/ Name;
+ string compileName;
+ public string CompileName {
+ get {
+ if (compileName == null) {
+ compileName = NonglobalVariable.CompilerizeName(Name);
+ }
+ return compileName;
+ }
+ }
public readonly Attributes Attributes;
public Declaration(IToken tok, string name, Attributes attributes) {
@@ -770,6 +803,11 @@ namespace Microsoft.Dafny { return Module.Name + "." + Name;
}
}
+ public string FullCompileName {
+ get {
+ return Module.CompileName + "." + CompileName;
+ }
+ }
}
public class ClassDecl : TopLevelDecl {
@@ -934,6 +972,14 @@ namespace Microsoft.Dafny { return EnclosingClass.FullName + "." + Name;
}
}
+ public string FullCompileName {
+ get {
+ Contract.Requires(EnclosingClass != null);
+ Contract.Ensures(Contract.Result<string>() != null);
+
+ return EnclosingClass.FullCompileName + "." + CompileName;
+ }
+ }
}
public class Field : MemberDecl {
@@ -1019,6 +1065,9 @@ namespace Microsoft.Dafny { string/*!*/ UniqueName {
get;
}
+ string/*!*/ CompileName {
+ get;
+ }
Type/*!*/ Type {
get;
}
@@ -1043,6 +1092,12 @@ namespace Microsoft.Dafny { throw new NotImplementedException();
}
}
+ public string CompileName {
+ get {
+ Contract.Ensures(Contract.Result<string>() != null);
+ throw new NotImplementedException();
+ }
+ }
public Type Type {
get {
Contract.Ensures(Contract.Result<Type>() != null);
@@ -1085,6 +1140,46 @@ namespace Microsoft.Dafny { return name + "#" + varId;
}
}
+ static char[] specialChars = new char[] { '\'', '_', '?', '\\' };
+ public static string CompilerizeName(string nm) {
+ string name = null;
+ int i = 0;
+ while (true) {
+ int j = nm.IndexOfAny(specialChars, i);
+ if (j == -1) {
+ if (i == 0) {
+ return nm; // this is the common case
+ } else {
+ return name + nm.Substring(i);
+ }
+ } else {
+ string nxt = nm.Substring(i, j);
+ name = name == null ? nxt : name + nxt;
+ switch (nm[j]) {
+ case '\'': name += "_k"; break;
+ case '_': name += "__"; break;
+ case '?': name += "_q"; break;
+ case '\\': name += "_b"; break;
+ default:
+ Contract.Assume(false); // unexpected character
+ break;
+ }
+ i = j + 1;
+ if (i == nm.Length) {
+ return name;
+ }
+ }
+ }
+ }
+ protected string compileName;
+ public virtual string CompileName {
+ get {
+ if (compileName == null) {
+ compileName = string.Format("_{0}_{1}", varId, CompilerizeName(name));
+ }
+ return compileName;
+ }
+ }
Type type;
//[Pure(false)] // TODO: if Type gets the status of [Frozen], then this attribute is not needed
public Type/*!*/ Type {
@@ -1140,6 +1235,14 @@ namespace Microsoft.Dafny { return !Name.StartsWith("#");
}
}
+ public override string CompileName {
+ get {
+ if (compileName == null) {
+ compileName = CompilerizeName(Name);
+ }
+ return compileName;
+ }
+ }
}
/// <summary>
@@ -1172,7 +1275,6 @@ namespace Microsoft.Dafny { public class Function : MemberDecl, TypeParameter.ParentType {
public readonly bool IsGhost; // functions are "ghost" by default; a non-ghost function is called a "function method"
- public readonly bool IsUnlimited;
public bool IsRecursive; // filled in during resolution
public readonly List<TypeParameter/*!*/>/*!*/ TypeArgs;
public readonly IToken OpenParen; // can be null (for predicates), if there are no formals
@@ -1195,7 +1297,7 @@ namespace Microsoft.Dafny { Contract.Invariant(Decreases != null);
}
- public Function(IToken tok, string name, bool isStatic, bool isGhost, bool isUnlimited,
+ public Function(IToken tok, string name, bool isStatic, bool isGhost,
List<TypeParameter> typeArgs, IToken openParen, List<Formal> formals, Type resultType,
List<Expression> req, List<FrameExpression> reads, List<Expression> ens, Specification<Expression> decreases,
Expression body, Attributes attributes, bool signatureOmitted)
@@ -1211,7 +1313,6 @@ namespace Microsoft.Dafny { Contract.Requires(cce.NonNullElements(ens));
Contract.Requires(decreases != null);
this.IsGhost = isGhost;
- this.IsUnlimited = isUnlimited;
this.TypeArgs = typeArgs;
this.OpenParen = openParen;
this.Formals = formals;
@@ -1228,11 +1329,11 @@ namespace Microsoft.Dafny { public class Predicate : Function
{
public readonly bool BodyIsExtended; // says that this predicate definition is a refinement extension of a predicate definition is a refining module
- public Predicate(IToken tok, string name, bool isStatic, bool isGhost, bool isUnlimited,
+ public Predicate(IToken tok, string name, bool isStatic, bool isGhost,
List<TypeParameter> typeArgs, IToken openParen, List<Formal> formals,
List<Expression> req, List<FrameExpression> reads, List<Expression> ens, Specification<Expression> decreases,
Expression body, bool bodyIsExtended, Attributes attributes, bool signatureOmitted)
- : base(tok, name, isStatic, isGhost, isUnlimited, typeArgs, openParen, formals, new BoolType(), req, reads, ens, decreases, body, attributes, signatureOmitted) {
+ : base(tok, name, isStatic, isGhost, typeArgs, openParen, formals, new BoolType(), req, reads, ens, decreases, body, attributes, signatureOmitted) {
Contract.Requires(!bodyIsExtended || body != null);
BodyIsExtended = bodyIsExtended;
}
@@ -1320,7 +1421,7 @@ namespace Microsoft.Dafny { public abstract class Statement {
public readonly IToken Tok;
- public LabelNode Labels; // mutable during resolution
+ public LList<Label> Labels; // mutable during resolution
private Attributes attributes;
public Attributes Attributes {
@@ -1363,19 +1464,43 @@ namespace Microsoft.Dafny { }
}
- public class LabelNode
+ public class LList<T>
+ {
+ public readonly T Data;
+ public readonly LList<T> Next;
+ const LList<T> Empty = null;
+
+ public LList(T d, LList<T> next) {
+ Data = d;
+ Next = next;
+ }
+
+ public static LList<T> Append(LList<T> a, LList<T> b) {
+ if (a == null) return b;
+ return new LList<T>(a.Data, Append(a.Next, b));
+ // pretend this is ML
+ }
+ public static int Count(LList<T> n) {
+ int count = 0;
+ while (n != null) {
+ count++;
+ n = n.Next;
+ }
+ return count;
+ }
+ }
+
+ public class Label
{
public readonly IToken Tok;
- public readonly string Label;
+ public readonly string Name;
public readonly int UniqueId;
- public readonly LabelNode Next;
static int nodes = 0;
- public LabelNode(IToken tok, string label, LabelNode next) {
+ public Label(IToken tok, string label) {
Contract.Requires(tok != null);
Tok = tok;
- Label = label;
- Next = next;
+ Name = label;
UniqueId = nodes++;
}
}
@@ -1676,14 +1801,22 @@ namespace Microsoft.Dafny { public class AssignSuchThatStmt : ConcreteUpdateStatement
{
- public readonly AssumeStmt Assume;
- public AssignSuchThatStmt(IToken tok, List<Expression> lhss, Expression expr)
+ public readonly Expression Expr;
+ public readonly IToken AssumeToken;
+ /// <summary>
+ /// "assumeToken" is allowed to be "null", in which case the verifier will check that a RHS value exists.
+ /// If "assumeToken" is non-null, then it should denote the "assume" keyword used in the statement.
+ /// </summary>
+ public AssignSuchThatStmt(IToken tok, List<Expression> lhss, Expression expr, IToken assumeToken)
: base(tok, lhss) {
Contract.Requires(tok != null);
Contract.Requires(cce.NonNullElements(lhss));
Contract.Requires(lhss.Count != 0);
Contract.Requires(expr != null);
- Assume = new AssumeStmt(tok, expr);
+ Expr = expr;
+ if (assumeToken != null) {
+ AssumeToken = assumeToken;
+ }
}
}
@@ -1744,6 +1877,24 @@ namespace Microsoft.Dafny { }
}
}
+
+ /// <summary>
+ /// This method assumes "lhs" has been successfully resolved.
+ /// </summary>
+ public static bool LhsIsToGhost(Expression lhs) {
+ Contract.Requires(lhs != null);
+ lhs = lhs.Resolved;
+ if (lhs is IdentifierExpr) {
+ var x = (IdentifierExpr)lhs;
+ return x.Var.IsGhost;
+ } else if (lhs is FieldSelectExpr) {
+ var x = (FieldSelectExpr)lhs;
+ return x.Field.IsGhost;
+ } else {
+ // LHS denotes an array element, which is always non-ghost
+ return false;
+ }
+ }
}
public class VarDecl : Statement, IVariable {
@@ -1778,6 +1929,15 @@ namespace Microsoft.Dafny { return name + "#" + varId;
}
}
+ string compileName;
+ public string CompileName {
+ get {
+ if (compileName == null) {
+ compileName = string.Format("_{0}_{1}", varId, NonglobalVariable.CompilerizeName(name));
+ }
+ return compileName;
+ }
+ }
public readonly Type OptionalType; // this is the type mentioned in the declaration, if any
internal Type type; // this is the declared or inferred type of the variable; it is non-null after resolution (even if resolution fails)
//[Pure(false)]
diff --git a/Source/Dafny/Parser.cs b/Source/Dafny/Parser.cs index fe4d58a9..9a439914 100644 --- a/Source/Dafny/Parser.cs +++ b/Source/Dafny/Parser.cs @@ -21,7 +21,7 @@ public class Parser { public const int _colon = 5;
public const int _lbrace = 6;
public const int _rbrace = 7;
- public const int maxT = 108;
+ public const int maxT = 107;
const bool T = true;
const bool x = false;
@@ -44,7 +44,6 @@ static int anonymousIds = 0; struct MemberModifiers {
public bool IsGhost;
public bool IsStatic;
- public bool IsUnlimited;
}
// helper routine for parsing call statements
///<summary>
@@ -231,10 +230,10 @@ bool IsAttribute() { if (la.kind == 12) {
ClassDecl(module, out c);
module.TopLevelDecls.Add(c);
- } else if (la.kind == 15 || la.kind == 16) {
+ } else if (la.kind == 14 || la.kind == 15) {
DatatypeDecl(module, out dt);
module.TopLevelDecls.Add(dt);
- } else if (la.kind == 22) {
+ } else if (la.kind == 21) {
ArbitraryTypeDecl(module, out at);
module.TopLevelDecls.Add(at);
} else {
@@ -249,17 +248,17 @@ bool IsAttribute() { 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 || la.kind == 16) {
+ } else if (la.kind == 14 || la.kind == 15) {
if (isGhost) { SemErr(t, "a datatype/codatatype is not allowed to be declared as 'ghost'"); }
DatatypeDecl(defaultModule, out dt);
defaultModule.TopLevelDecls.Add(dt);
- } else if (la.kind == 22) {
+ } 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 if (StartOf(3)) {
ClassMemberDecl(membersDefaultClass, isGhost, false);
- } else SynErr(109);
+ } else SynErr(108);
}
if (defaultModuleCreatedHere) {
defaultModule.TopLevelDecls.Add(new DefaultClassDecl(defaultModule, membersDefaultClass));
@@ -294,7 +293,7 @@ bool IsAttribute() { IToken/*!*/ id;
Ident(out id);
ids.Add(id.val);
- while (la.kind == 21) {
+ while (la.kind == 20) {
Get();
Ident(out id);
ids.Add(id.val);
@@ -310,13 +309,13 @@ bool IsAttribute() { List<MemberDecl/*!*/> members = new List<MemberDecl/*!*/>();
IToken bodyStart;
- while (!(la.kind == 0 || la.kind == 12)) {SynErr(110); Get();}
+ while (!(la.kind == 0 || la.kind == 12)) {SynErr(109); Get();}
Expect(12);
while (la.kind == 6) {
Attribute(ref attrs);
}
Ident(out id);
- if (la.kind == 23) {
+ if (la.kind == 22) {
GenericParameters(typeArgs);
}
Expect(6);
@@ -341,29 +340,29 @@ bool IsAttribute() { IToken bodyStart = Token.NoToken; // dummy assignment
bool co = false;
- while (!(la.kind == 0 || la.kind == 15 || la.kind == 16)) {SynErr(111); Get();}
- if (la.kind == 15) {
+ while (!(la.kind == 0 || la.kind == 14 || la.kind == 15)) {SynErr(110); Get();}
+ if (la.kind == 14) {
Get();
- } else if (la.kind == 16) {
+ } else if (la.kind == 15) {
Get();
co = true;
- } else SynErr(112);
+ } else SynErr(111);
while (la.kind == 6) {
Attribute(ref attrs);
}
Ident(out id);
- if (la.kind == 23) {
+ if (la.kind == 22) {
GenericParameters(typeArgs);
}
- Expect(17);
+ Expect(16);
bodyStart = t;
DatatypeMemberDecl(ctors);
- while (la.kind == 18) {
+ while (la.kind == 17) {
Get();
DatatypeMemberDecl(ctors);
}
- while (!(la.kind == 0 || la.kind == 19)) {SynErr(113); Get();}
- Expect(19);
+ while (!(la.kind == 0 || la.kind == 18)) {SynErr(112); Get();}
+ Expect(18);
if (co) {
dt = new CoDatatypeDecl(id, id.val, module, typeArgs, ctors, attrs);
} else {
@@ -378,14 +377,14 @@ bool IsAttribute() { IToken/*!*/ id;
Attributes attrs = null;
- Expect(22);
+ Expect(21);
while (la.kind == 6) {
Attribute(ref attrs);
}
Ident(out id);
at = new ArbitraryTypeDecl(id, id.val, module, attrs);
- while (!(la.kind == 0 || la.kind == 19)) {SynErr(114); Get();}
- Expect(19);
+ while (!(la.kind == 0 || la.kind == 18)) {SynErr(113); Get();}
+ Expect(18);
}
void ClassMemberDecl(List<MemberDecl/*!*/>/*!*/ mm, bool isAlreadyGhost, bool allowConstructors) {
@@ -395,41 +394,38 @@ bool IsAttribute() { MemberModifiers mmod = new MemberModifiers();
mmod.IsGhost = isAlreadyGhost;
- while (la.kind == 8 || la.kind == 13 || la.kind == 14) {
+ while (la.kind == 8 || la.kind == 13) {
if (la.kind == 8) {
Get();
mmod.IsGhost = true;
- } else if (la.kind == 13) {
- Get();
- mmod.IsStatic = true;
} else {
Get();
- mmod.IsUnlimited = true;
+ mmod.IsStatic = true;
}
}
- if (la.kind == 20) {
+ if (la.kind == 19) {
FieldDecl(mmod, mm);
} else if (la.kind == 44 || la.kind == 45) {
FunctionDecl(mmod, out f);
mm.Add(f);
- } else if (la.kind == 25 || la.kind == 26) {
+ } else if (la.kind == 24 || la.kind == 25) {
MethodDecl(mmod, allowConstructors, out m);
mm.Add(m);
- } else SynErr(115);
+ } else SynErr(114);
}
void GenericParameters(List<TypeParameter/*!*/>/*!*/ typeArgs) {
Contract.Requires(cce.NonNullElements(typeArgs));
IToken/*!*/ id;
- Expect(23);
+ Expect(22);
Ident(out id);
typeArgs.Add(new TypeParameter(id, id.val));
- while (la.kind == 21) {
+ while (la.kind == 20) {
Get();
Ident(out id);
typeArgs.Add(new TypeParameter(id, id.val));
}
- Expect(24);
+ Expect(23);
}
void FieldDecl(MemberModifiers mmod, List<MemberDecl/*!*/>/*!*/ mm) {
@@ -437,9 +433,8 @@ bool IsAttribute() { Attributes attrs = null;
IToken/*!*/ id; Type/*!*/ ty;
- while (!(la.kind == 0 || la.kind == 20)) {SynErr(116); Get();}
- Expect(20);
- if (mmod.IsUnlimited) { SemErr(t, "fields cannot be declared 'unlimited'"); }
+ while (!(la.kind == 0 || la.kind == 19)) {SynErr(115); Get();}
+ Expect(19);
if (mmod.IsStatic) { SemErr(t, "fields cannot be declared 'static'"); }
while (la.kind == 6) {
@@ -447,13 +442,13 @@ bool IsAttribute() { }
IdentType(out id, out ty);
mm.Add(new Field(id, id.val, mmod.IsGhost, ty, attrs));
- while (la.kind == 21) {
+ while (la.kind == 20) {
Get();
IdentType(out id, out ty);
mm.Add(new Field(id, id.val, mmod.IsGhost, ty, attrs));
}
- while (!(la.kind == 0 || la.kind == 19)) {SynErr(117); Get();}
- Expect(19);
+ while (!(la.kind == 0 || la.kind == 18)) {SynErr(116); Get();}
+ Expect(18);
}
void FunctionDecl(MemberModifiers mmod, out Function/*!*/ f) {
@@ -477,7 +472,7 @@ bool IsAttribute() { if (la.kind == 44) {
Get();
- if (la.kind == 25) {
+ if (la.kind == 24) {
Get();
isFunctionMethod = true;
}
@@ -487,22 +482,22 @@ bool IsAttribute() { Attribute(ref attrs);
}
Ident(out id);
- if (la.kind == 23 || la.kind == 34) {
- if (la.kind == 23) {
+ if (la.kind == 22 || la.kind == 33) {
+ if (la.kind == 22) {
GenericParameters(typeArgs);
}
Formals(true, isFunctionMethod, formals, out openParen);
Expect(5);
Type(out returnType);
- } else if (la.kind == 28) {
+ } else if (la.kind == 27) {
Get();
signatureOmitted = true;
openParen = Token.NoToken;
- } else SynErr(118);
+ } else SynErr(117);
} else if (la.kind == 45) {
Get();
isPredicate = true;
- if (la.kind == 25) {
+ if (la.kind == 24) {
Get();
isFunctionMethod = true;
}
@@ -513,22 +508,22 @@ bool IsAttribute() { }
Ident(out id);
if (StartOf(4)) {
- if (la.kind == 23) {
+ if (la.kind == 22) {
GenericParameters(typeArgs);
}
- if (la.kind == 34) {
+ if (la.kind == 33) {
Formals(true, isFunctionMethod, formals, out openParen);
if (la.kind == 5) {
Get();
SemErr(t, "predicates do not have an explicitly declared return type; it is always bool");
}
}
- } else if (la.kind == 28) {
+ } else if (la.kind == 27) {
Get();
signatureOmitted = true;
openParen = Token.NoToken;
- } else SynErr(119);
- } else SynErr(120);
+ } else SynErr(118);
+ } else SynErr(119);
while (StartOf(5)) {
FunctionSpec(reqs, reads, ens, decreases);
}
@@ -536,10 +531,10 @@ bool IsAttribute() { FunctionBody(out body, out bodyStart, out bodyEnd);
}
if (isPredicate) {
- f = new Predicate(id, id.val, mmod.IsStatic, !isFunctionMethod, mmod.IsUnlimited, typeArgs, openParen, formals,
+ f = new Predicate(id, id.val, mmod.IsStatic, !isFunctionMethod, typeArgs, openParen, formals,
reqs, reads, ens, new Specification<Expression>(decreases, null), body, false, attrs, signatureOmitted);
} else {
- f = new Function(id, id.val, mmod.IsStatic, !isFunctionMethod, mmod.IsUnlimited, typeArgs, openParen, formals, returnType,
+ f = new Function(id, id.val, mmod.IsStatic, !isFunctionMethod, typeArgs, openParen, formals, returnType,
reqs, reads, ens, new Specification<Expression>(decreases, null), body, attrs, signatureOmitted);
}
f.BodyStartTok = bodyStart;
@@ -567,10 +562,10 @@ bool IsAttribute() { IToken bodyStart = Token.NoToken;
IToken bodyEnd = Token.NoToken;
- while (!(la.kind == 0 || la.kind == 25 || la.kind == 26)) {SynErr(121); Get();}
- if (la.kind == 25) {
+ while (!(la.kind == 0 || la.kind == 24 || la.kind == 25)) {SynErr(120); Get();}
+ if (la.kind == 24) {
Get();
- } else if (la.kind == 26) {
+ } else if (la.kind == 25) {
Get();
if (allowConstructor) {
isConstructor = true;
@@ -578,8 +573,7 @@ bool IsAttribute() { SemErr(t, "constructors are only allowed in classes");
}
- } else SynErr(122);
- if (mmod.IsUnlimited) { SemErr(t, "methods cannot be declared 'unlimited'"); }
+ } else SynErr(121);
if (isConstructor) {
if (mmod.IsGhost) {
SemErr(t, "constructors cannot be declared 'ghost'");
@@ -593,20 +587,20 @@ bool IsAttribute() { Attribute(ref attrs);
}
Ident(out id);
- if (la.kind == 23 || la.kind == 34) {
- if (la.kind == 23) {
+ if (la.kind == 22 || la.kind == 33) {
+ if (la.kind == 22) {
GenericParameters(typeArgs);
}
Formals(true, !mmod.IsGhost, ins, out openParen);
- if (la.kind == 27) {
+ if (la.kind == 26) {
Get();
if (isConstructor) { SemErr(t, "constructors cannot have out-parameters"); }
Formals(false, !mmod.IsGhost, outs, out openParen);
}
- } else if (la.kind == 28) {
+ } else if (la.kind == 27) {
Get();
signatureOmitted = true; openParen = Token.NoToken;
- } else SynErr(123);
+ } else SynErr(122);
while (StartOf(6)) {
MethodSpec(req, mod, ens, dec, ref decAttrs, ref modAttrs);
}
@@ -635,7 +629,7 @@ bool IsAttribute() { Attribute(ref attrs);
}
Ident(out id);
- if (la.kind == 34) {
+ if (la.kind == 33) {
FormalsOptionalIds(formals);
}
ctors.Add(new DatatypeCtor(id, id.val, formals, attrs));
@@ -643,17 +637,17 @@ bool IsAttribute() { void FormalsOptionalIds(List<Formal/*!*/>/*!*/ formals) {
Contract.Requires(cce.NonNullElements(formals)); IToken/*!*/ id; Type/*!*/ ty; string/*!*/ name; bool isGhost;
- Expect(34);
+ Expect(33);
if (StartOf(7)) {
TypeIdentOptional(out id, out name, out ty, out isGhost);
formals.Add(new Formal(id, name, ty, true, isGhost));
- while (la.kind == 21) {
+ while (la.kind == 20) {
Get();
TypeIdentOptional(out id, out name, out ty, out isGhost);
formals.Add(new Formal(id, name, ty, true, isGhost));
}
}
- Expect(35);
+ Expect(34);
}
void IdentType(out IToken/*!*/ id, out Type/*!*/ ty) {
@@ -737,22 +731,22 @@ bool IsAttribute() { List<Type/*!*/>/*!*/ gt;
switch (la.kind) {
- case 36: {
+ case 35: {
Get();
tok = t;
break;
}
- case 37: {
+ case 36: {
Get();
tok = t; ty = new NatType();
break;
}
- case 38: {
+ case 37: {
Get();
tok = t; ty = new IntType();
break;
}
- case 39: {
+ case 38: {
Get();
tok = t; gt = new List<Type/*!*/>();
GenericInstantiation(gt);
@@ -763,7 +757,7 @@ bool IsAttribute() { break;
}
- case 40: {
+ case 39: {
Get();
tok = t; gt = new List<Type/*!*/>();
GenericInstantiation(gt);
@@ -774,7 +768,7 @@ bool IsAttribute() { break;
}
- case 41: {
+ case 40: {
Get();
tok = t; gt = new List<Type/*!*/>();
GenericInstantiation(gt);
@@ -785,39 +779,39 @@ bool IsAttribute() { break;
}
- case 42: {
+ case 41: {
Get();
tok = t; gt = new List<Type/*!*/>();
GenericInstantiation(gt);
if (gt.Count != 2) {
SemErr("map type expects exactly two type arguments");
}
- ty = new MapType(gt[0], gt[1]);
+ else { ty = new MapType(gt[0], gt[1]); }
break;
}
- case 1: case 3: case 43: {
+ case 1: case 3: case 42: {
ReferenceType(out tok, out ty);
break;
}
- default: SynErr(124); break;
+ default: SynErr(123); break;
}
}
void Formals(bool incoming, bool allowGhostKeyword, List<Formal/*!*/>/*!*/ formals, out IToken openParen) {
Contract.Requires(cce.NonNullElements(formals)); IToken/*!*/ id; Type/*!*/ ty; bool isGhost;
- Expect(34);
+ Expect(33);
openParen = t;
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 == 21) {
+ while (la.kind == 20) {
Get();
GIdentType(allowGhostKeyword, out id, out ty, out isGhost);
formals.Add(new Formal(id, id.val, ty, incoming, isGhost));
}
}
- Expect(35);
+ Expect(34);
}
void MethodSpec(List<MaybeFreeExpression/*!*/>/*!*/ req, List<FrameExpression/*!*/>/*!*/ mod, List<MaybeFreeExpression/*!*/>/*!*/ ens,
@@ -825,8 +819,8 @@ 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(125); Get();}
- if (la.kind == 29) {
+ while (!(StartOf(8))) {SynErr(124); Get();}
+ if (la.kind == 28) {
Get();
while (IsAttribute()) {
Attribute(ref modAttrs);
@@ -834,44 +828,44 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo if (StartOf(9)) {
FrameExpression(out fe);
mod.Add(fe);
- while (la.kind == 21) {
+ while (la.kind == 20) {
Get();
FrameExpression(out fe);
mod.Add(fe);
}
}
- while (!(la.kind == 0 || la.kind == 19)) {SynErr(126); Get();}
- Expect(19);
- } else if (la.kind == 30 || la.kind == 31 || la.kind == 32) {
- if (la.kind == 30) {
+ while (!(la.kind == 0 || la.kind == 18)) {SynErr(125); Get();}
+ Expect(18);
+ } else if (la.kind == 29 || la.kind == 30 || la.kind == 31) {
+ if (la.kind == 29) {
Get();
isFree = true;
}
- if (la.kind == 31) {
+ if (la.kind == 30) {
Get();
Expression(out e);
- while (!(la.kind == 0 || la.kind == 19)) {SynErr(127); Get();}
- Expect(19);
+ while (!(la.kind == 0 || la.kind == 18)) {SynErr(126); Get();}
+ Expect(18);
req.Add(new MaybeFreeExpression(e, isFree));
- } else if (la.kind == 32) {
+ } else if (la.kind == 31) {
Get();
while (IsAttribute()) {
Attribute(ref ensAttrs);
}
Expression(out e);
- while (!(la.kind == 0 || la.kind == 19)) {SynErr(128); Get();}
- Expect(19);
+ while (!(la.kind == 0 || la.kind == 18)) {SynErr(127); Get();}
+ Expect(18);
ens.Add(new MaybeFreeExpression(e, isFree, ensAttrs));
- } else SynErr(129);
- } else if (la.kind == 33) {
+ } else SynErr(128);
+ } else if (la.kind == 32) {
Get();
while (IsAttribute()) {
Attribute(ref decAttrs);
}
DecreasesList(decreases, false);
- while (!(la.kind == 0 || la.kind == 19)) {SynErr(130); Get();}
- Expect(19);
- } else SynErr(131);
+ while (!(la.kind == 0 || la.kind == 18)) {SynErr(129); Get();}
+ Expect(18);
+ } else SynErr(130);
}
void BlockStmt(out BlockStmt/*!*/ block, out IToken bodyStart, out IToken bodyEnd) {
@@ -912,7 +906,7 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo decreases.Add(e);
}
- while (la.kind == 21) {
+ while (la.kind == 20) {
Get();
PossiblyWildExpression(out e);
if (!allowWildcard && e is WildcardExpr) {
@@ -926,23 +920,24 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo void GenericInstantiation(List<Type/*!*/>/*!*/ gt) {
Contract.Requires(cce.NonNullElements(gt)); Type/*!*/ ty;
- Expect(23);
+ Expect(22);
Type(out ty);
gt.Add(ty);
- while (la.kind == 21) {
+ while (la.kind == 20) {
Get();
Type(out ty);
gt.Add(ty);
}
- Expect(24);
+ Expect(23);
}
void ReferenceType(out IToken/*!*/ tok, out Type/*!*/ ty) {
Contract.Ensures(Contract.ValueAtReturn(out tok) != null); Contract.Ensures(Contract.ValueAtReturn(out ty) != null);
tok = Token.NoToken; ty = new BoolType(); /*keep compiler happy*/
+ IToken moduleName = null;
List<Type/*!*/>/*!*/ gt;
- if (la.kind == 43) {
+ if (la.kind == 42) {
Get();
tok = t; ty = new ObjectType();
} else if (la.kind == 3) {
@@ -961,48 +956,53 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo } else if (la.kind == 1) {
Ident(out tok);
gt = new List<Type/*!*/>();
- if (la.kind == 23) {
+ if (la.kind == 43) {
+ moduleName = tok;
+ Get();
+ Ident(out tok);
+ }
+ if (la.kind == 22) {
GenericInstantiation(gt);
}
- ty = new UserDefinedType(tok, tok.val, gt);
- } else SynErr(132);
+ ty = new UserDefinedType(tok, tok.val, gt, moduleName);
+ } else SynErr(131);
}
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 == 31) {
- while (!(la.kind == 0 || la.kind == 31)) {SynErr(133); Get();}
+ if (la.kind == 30) {
+ while (!(la.kind == 0 || la.kind == 30)) {SynErr(132); Get();}
Get();
Expression(out e);
- while (!(la.kind == 0 || la.kind == 19)) {SynErr(134); Get();}
- Expect(19);
+ while (!(la.kind == 0 || la.kind == 18)) {SynErr(133); Get();}
+ Expect(18);
reqs.Add(e);
} else if (la.kind == 46) {
Get();
if (StartOf(11)) {
PossiblyWildFrameExpression(out fe);
reads.Add(fe);
- while (la.kind == 21) {
+ while (la.kind == 20) {
Get();
PossiblyWildFrameExpression(out fe);
reads.Add(fe);
}
}
- while (!(la.kind == 0 || la.kind == 19)) {SynErr(135); Get();}
- Expect(19);
- } else if (la.kind == 32) {
+ while (!(la.kind == 0 || la.kind == 18)) {SynErr(134); Get();}
+ Expect(18);
+ } else if (la.kind == 31) {
Get();
Expression(out e);
- while (!(la.kind == 0 || la.kind == 19)) {SynErr(136); Get();}
- Expect(19);
+ while (!(la.kind == 0 || la.kind == 18)) {SynErr(135); Get();}
+ Expect(18);
ens.Add(e);
- } else if (la.kind == 33) {
+ } else if (la.kind == 32) {
Get();
DecreasesList(decreases, false);
- while (!(la.kind == 0 || la.kind == 19)) {SynErr(137); Get();}
- Expect(19);
- } else SynErr(138);
+ while (!(la.kind == 0 || la.kind == 18)) {SynErr(136); Get();}
+ Expect(18);
+ } else SynErr(137);
}
void FunctionBody(out Expression/*!*/ e, out IToken bodyStart, out IToken bodyEnd) {
@@ -1021,7 +1021,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(139);
+ } else SynErr(138);
}
void PossiblyWildExpression(out Expression/*!*/ e) {
@@ -1032,7 +1032,7 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo e = new WildcardExpr(t);
} else if (StartOf(9)) {
Expression(out e);
- } else SynErr(140);
+ } else SynErr(139);
}
void Stmt(List<Statement/*!*/>/*!*/ ss) {
@@ -1049,7 +1049,7 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo IToken bodyStart, bodyEnd;
int breakCount;
- while (!(StartOf(12))) {SynErr(141); Get();}
+ while (!(StartOf(12))) {SynErr(140); Get();}
switch (la.kind) {
case 6: {
BlockStmt(out bs, out bodyStart, out bodyEnd);
@@ -1060,19 +1060,19 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo AssertStmt(out s);
break;
}
- case 67: {
+ case 54: {
AssumeStmt(out s);
break;
}
- case 68: {
+ case 67: {
PrintStmt(out s);
break;
}
- case 1: case 2: case 18: case 34: case 93: case 94: case 95: case 96: case 97: case 98: case 99: {
+ case 1: case 2: case 17: case 33: case 92: case 93: case 94: case 95: case 96: case 97: case 98: {
UpdateStmt(out s);
break;
}
- case 8: case 20: {
+ case 8: case 19: {
VarDeclStatement(out s);
break;
}
@@ -1088,7 +1088,7 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo MatchStmt(out s);
break;
}
- case 69: {
+ case 68: {
ParallelStmt(out s);
break;
}
@@ -1098,7 +1098,7 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo Ident(out id);
Expect(5);
OneStmt(out s);
- s.Labels = new LabelNode(x, id.val, s.Labels);
+ s.Labels = new LList<Label>(new Label(x, id.val), s.Labels);
break;
}
case 50: {
@@ -1107,14 +1107,14 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo if (la.kind == 1) {
Ident(out id);
label = id.val;
- } else if (la.kind == 19 || la.kind == 50) {
+ } else if (la.kind == 18 || la.kind == 50) {
while (la.kind == 50) {
Get();
breakCount++;
}
- } else SynErr(142);
- while (!(la.kind == 0 || la.kind == 19)) {SynErr(143); Get();}
- Expect(19);
+ } else SynErr(141);
+ while (!(la.kind == 0 || la.kind == 18)) {SynErr(142); Get();}
+ Expect(18);
s = label != null ? new BreakStmt(x, label) : new BreakStmt(x, breakCount);
break;
}
@@ -1122,13 +1122,13 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo ReturnStmt(out s);
break;
}
- case 28: {
+ case 27: {
Get();
s = new SkeletonStatement(t);
- Expect(19);
+ Expect(18);
break;
}
- default: SynErr(144); break;
+ default: SynErr(143); break;
}
}
@@ -1143,10 +1143,10 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo }
if (StartOf(9)) {
Expression(out e);
- } else if (la.kind == 28) {
+ } else if (la.kind == 27) {
Get();
- } else SynErr(145);
- Expect(19);
+ } else SynErr(144);
+ Expect(18);
if (e == null) {
s = new SkeletonStatement(new AssertStmt(x, new LiteralExpr(x, true), attrs), true, false);
} else {
@@ -1157,10 +1157,10 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo void AssumeStmt(out Statement/*!*/ s) {
Contract.Ensures(Contract.ValueAtReturn(out s) != null); IToken/*!*/ x; Expression/*!*/ e;
- Expect(67);
+ Expect(54);
x = t;
Expression(out e);
- Expect(19);
+ Expect(18);
s = new AssumeStmt(x, e);
}
@@ -1168,16 +1168,16 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo Contract.Ensures(Contract.ValueAtReturn(out s) != null); IToken/*!*/ x; Attributes.Argument/*!*/ arg;
List<Attributes.Argument/*!*/> args = new List<Attributes.Argument/*!*/>();
- Expect(68);
+ Expect(67);
x = t;
AttributeArg(out arg);
args.Add(arg);
- while (la.kind == 21) {
+ while (la.kind == 20) {
Get();
AttributeArg(out arg);
args.Add(arg);
}
- Expect(19);
+ Expect(18);
s = new PrintStmt(x, args);
}
@@ -1188,19 +1188,20 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo Expression lhs0;
IToken x;
Attributes attrs = null;
+ IToken suchThatAssume = null;
Expression suchThat = null;
Lhs(out e);
x = e.tok;
- if (la.kind == 6 || la.kind == 19) {
+ if (la.kind == 6 || la.kind == 18) {
while (la.kind == 6) {
Attribute(ref attrs);
}
- Expect(19);
+ Expect(18);
rhss.Add(new ExprRhs(e, attrs));
- } else if (la.kind == 21 || la.kind == 52 || la.kind == 53) {
+ } else if (la.kind == 20 || la.kind == 52 || la.kind == 53) {
lhss.Add(e); lhs0 = e;
- while (la.kind == 21) {
+ while (la.kind == 20) {
Get();
Lhs(out e);
lhss.Add(e);
@@ -1210,7 +1211,7 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo x = t;
Rhs(out r, lhs0);
rhss.Add(r);
- while (la.kind == 21) {
+ while (la.kind == 20) {
Get();
Rhs(out r, lhs0);
rhss.Add(r);
@@ -1218,15 +1219,19 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo } else if (la.kind == 53) {
Get();
x = t;
+ if (la.kind == 54) {
+ Get();
+ suchThatAssume = t;
+ }
Expression(out suchThat);
- } else SynErr(146);
- Expect(19);
+ } else SynErr(145);
+ Expect(18);
} else if (la.kind == 5) {
Get();
SemErr(t, "invalid statement (did you forget the 'label' keyword?)");
- } else SynErr(147);
+ } else SynErr(146);
if (suchThat != null) {
- s = new AssignSuchThatStmt(x, lhss, suchThat);
+ s = new AssignSuchThatStmt(x, lhss, suchThat, suchThatAssume);
} else {
s = new UpdateStmt(x, lhss, rhss);
}
@@ -1239,17 +1244,18 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo AssignmentRhs r; IdentifierExpr lhs0;
List<VarDecl> lhss = new List<VarDecl>();
List<AssignmentRhs> rhss = new List<AssignmentRhs>();
+ IToken suchThatAssume = null;
Expression suchThat = null;
if (la.kind == 8) {
Get();
isGhost = true; x = t;
}
- Expect(20);
+ Expect(19);
if (!isGhost) { x = t; }
LocalIdentTypeOptional(out d, isGhost);
lhss.Add(d);
- while (la.kind == 21) {
+ while (la.kind == 20) {
Get();
LocalIdentTypeOptional(out d, isGhost);
lhss.Add(d);
@@ -1263,7 +1269,7 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo Rhs(out r, lhs0);
rhss.Add(r);
- while (la.kind == 21) {
+ while (la.kind == 20) {
Get();
Rhs(out r, lhs0);
rhss.Add(r);
@@ -1271,17 +1277,21 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo } else {
Get();
assignTok = t;
+ if (la.kind == 54) {
+ Get();
+ suchThatAssume = t;
+ }
Expression(out suchThat);
}
}
- Expect(19);
+ Expect(18);
ConcreteUpdateStatement update;
if (suchThat != null) {
var ies = new List<Expression>();
foreach (var lhs in lhss) {
ies.Add(new IdentifierExpr(lhs.Tok, lhs.Name));
}
- update = new AssignSuchThatStmt(assignTok, ies, suchThat);
+ update = new AssignSuchThatStmt(assignTok, ies, suchThat, suchThatAssume);
} else if (rhss.Count == 0) {
update = null;
} else {
@@ -1308,8 +1318,8 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo Expect(59);
x = t;
- if (la.kind == 28 || la.kind == 34) {
- if (la.kind == 34) {
+ if (la.kind == 27 || la.kind == 33) {
+ if (la.kind == 33) {
Guard(out guard);
} else {
Get();
@@ -1324,7 +1334,7 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo } else if (la.kind == 6) {
BlockStmt(out bs, out bodyStart, out bodyEnd);
els = bs;
- } else SynErr(148);
+ } else SynErr(147);
}
if (guardOmitted) {
ifStmt = new SkeletonStatement(new IfStmt(x, guard, thn, els), true, false);
@@ -1335,7 +1345,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(149);
+ } else SynErr(148);
}
void WhileStmt(out Statement/*!*/ stmt) {
@@ -1353,8 +1363,8 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo Expect(63);
x = t;
- if (la.kind == 28 || la.kind == 34) {
- if (la.kind == 34) {
+ if (la.kind == 27 || la.kind == 33) {
+ if (la.kind == 33) {
Guard(out guard);
Contract.Assume(guard == null || cce.Owner.None(guard));
} else {
@@ -1364,10 +1374,10 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo LoopSpec(out invariants, out decreases, out mod, ref decAttrs, ref modAttrs);
if (la.kind == 6) {
BlockStmt(out body, out bodyStart, out bodyEnd);
- } else if (la.kind == 28) {
+ } else if (la.kind == 27) {
Get();
bodyOmitted = true;
- } else SynErr(150);
+ } else SynErr(149);
if (guardOmitted || bodyOmitted) {
if (decreases.Count != 0) {
SemErr(decreases[0].tok, "'decreases' clauses are not allowed on refining loops");
@@ -1388,7 +1398,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(151);
+ } else SynErr(150);
}
void MatchStmt(out Statement/*!*/ s) {
@@ -1419,9 +1429,9 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo BlockStmt/*!*/ block;
IToken bodyStart, bodyEnd;
- Expect(69);
+ Expect(68);
x = t;
- Expect(34);
+ Expect(33);
if (la.kind == 1) {
List<BoundVar/*!*/> bvarsX; Attributes attrsX; Expression rangeX;
QuantifierDomain(out bvarsX, out attrsX, out rangeX);
@@ -1431,16 +1441,16 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo if (bvars == null) { bvars = new List<BoundVar>(); }
if (range == null) { range = new LiteralExpr(x, true); }
- Expect(35);
- while (la.kind == 30 || la.kind == 32) {
+ Expect(34);
+ while (la.kind == 29 || la.kind == 31) {
isFree = false;
- if (la.kind == 30) {
+ if (la.kind == 29) {
Get();
isFree = true;
}
- Expect(32);
+ Expect(31);
Expression(out e);
- Expect(19);
+ Expect(18);
ens.Add(new MaybeFreeExpression(e, isFree));
}
BlockStmt(out block, out bodyStart, out bodyEnd);
@@ -1457,13 +1467,13 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo if (StartOf(14)) {
Rhs(out r, null);
rhss = new List<AssignmentRhs>(); rhss.Add(r);
- while (la.kind == 21) {
+ while (la.kind == 20) {
Get();
Rhs(out r, null);
rhss.Add(r);
}
}
- Expect(19);
+ Expect(18);
s = new ReturnStmt(returnTok, rhss);
}
@@ -1476,29 +1486,49 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo r = null; // to please compiler
Attributes attrs = null;
- if (la.kind == 54) {
+ if (la.kind == 55) {
Get();
newToken = t;
TypeAndToken(out x, out ty);
- if (la.kind == 55 || la.kind == 57) {
- if (la.kind == 55) {
+ if (la.kind == 33 || la.kind == 43 || la.kind == 56) {
+ if (la.kind == 56) {
Get();
ee = new List<Expression>();
Expressions(ee);
- Expect(56);
+ Expect(57);
UserDefinedType tmp = theBuiltIns.ArrayType(x, ee.Count, new IntType(), true);
- } else {
+ } else if (la.kind == 43) {
Get();
Ident(out x);
+ Expect(33);
+ args = new List<Expression/*!*/>();
+ if (StartOf(9)) {
+ Expressions(args);
+ }
Expect(34);
+ initCall = new CallStmt(x, new List<Expression>(), receiverForInitCall, x.val, args);
+ } else {
+ Get();
+ var udf = ty as UserDefinedType;
+ if (udf != null && udf.ModuleName != null && udf.TypeArgs.Count == 0) {
+ // The parsed name had the form "A.B", so treat "A" as the name of the type and "B" as
+ // the name of the constructor that's being invoked.
+ x = udf.tok;
+ ty = new UserDefinedType(udf.ModuleName, udf.ModuleName.val, new List<Type>(), null);
+ } else {
+ SemErr(t, "expected '.'");
+ x = null;
+ }
args = new List<Expression/*!*/>();
if (StartOf(9)) {
Expressions(args);
}
- Expect(35);
- initCall = new CallStmt(x, new List<Expression>(),
- receiverForInitCall, x.val, args);
+ Expect(34);
+ if (x != null) {
+ initCall = new CallStmt(x, new List<Expression>(), receiverForInitCall, x.val, args);
+ }
+
}
}
if (ee != null) {
@@ -1518,11 +1548,11 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo } else if (StartOf(9)) {
Expression(out e);
r = new ExprRhs(e);
- } else SynErr(152);
+ } else SynErr(151);
while (la.kind == 6) {
Attribute(ref attrs);
}
- r.Attributes = attrs;
+ if (r != null) r.Attributes = attrs;
}
void Lhs(out Expression e) {
@@ -1530,23 +1560,23 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo if (la.kind == 1) {
DottedIdentifiersAndFunction(out e);
- while (la.kind == 55 || la.kind == 57) {
+ while (la.kind == 43 || la.kind == 56) {
Suffix(ref e);
}
} else if (StartOf(15)) {
ConstAtomExpression(out e);
Suffix(ref e);
- while (la.kind == 55 || la.kind == 57) {
+ while (la.kind == 43 || la.kind == 56) {
Suffix(ref e);
}
- } else SynErr(153);
+ } else SynErr(152);
}
void Expressions(List<Expression/*!*/>/*!*/ args) {
Contract.Requires(cce.NonNullElements(args)); Expression/*!*/ e;
Expression(out e);
args.Add(e);
- while (la.kind == 21) {
+ while (la.kind == 20) {
Get();
Expression(out e);
args.Add(e);
@@ -1555,15 +1585,15 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo void Guard(out Expression e) {
Expression/*!*/ ee; e = null;
- Expect(34);
+ Expect(33);
if (la.kind == 47) {
Get();
e = null;
} else if (StartOf(9)) {
Expression(out ee);
e = ee;
- } else SynErr(154);
- Expect(35);
+ } else SynErr(153);
+ Expect(34);
}
void AlternativeBlock(out List<GuardedAlternative> alternatives) {
@@ -1595,22 +1625,22 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo mod = null;
while (StartOf(16)) {
- if (la.kind == 30 || la.kind == 64) {
+ if (la.kind == 29 || la.kind == 64) {
Invariant(out invariant);
- while (!(la.kind == 0 || la.kind == 19)) {SynErr(155); Get();}
- Expect(19);
+ while (!(la.kind == 0 || la.kind == 18)) {SynErr(154); Get();}
+ Expect(18);
invariants.Add(invariant);
- } else if (la.kind == 33) {
- while (!(la.kind == 0 || la.kind == 33)) {SynErr(156); Get();}
+ } else if (la.kind == 32) {
+ while (!(la.kind == 0 || la.kind == 32)) {SynErr(155); Get();}
Get();
while (IsAttribute()) {
Attribute(ref decAttrs);
}
DecreasesList(decreases, true);
- while (!(la.kind == 0 || la.kind == 19)) {SynErr(157); Get();}
- Expect(19);
+ while (!(la.kind == 0 || la.kind == 18)) {SynErr(156); Get();}
+ Expect(18);
} else {
- while (!(la.kind == 0 || la.kind == 29)) {SynErr(158); Get();}
+ while (!(la.kind == 0 || la.kind == 28)) {SynErr(157); Get();}
Get();
while (IsAttribute()) {
Attribute(ref modAttrs);
@@ -1619,22 +1649,22 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo if (StartOf(9)) {
FrameExpression(out fe);
mod.Add(fe);
- while (la.kind == 21) {
+ while (la.kind == 20) {
Get();
FrameExpression(out fe);
mod.Add(fe);
}
}
- while (!(la.kind == 0 || la.kind == 19)) {SynErr(159); Get();}
- Expect(19);
+ while (!(la.kind == 0 || la.kind == 18)) {SynErr(158); Get();}
+ Expect(18);
}
}
}
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 == 30 || la.kind == 64)) {SynErr(160); Get();}
- if (la.kind == 30) {
+ while (!(la.kind == 0 || la.kind == 29 || la.kind == 64)) {SynErr(159); Get();}
+ if (la.kind == 29) {
Get();
isFree = true;
}
@@ -1656,16 +1686,16 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo Expect(61);
x = t;
Ident(out id);
- if (la.kind == 34) {
+ if (la.kind == 33) {
Get();
IdentTypeOptional(out bv);
arguments.Add(bv);
- while (la.kind == 21) {
+ while (la.kind == 20) {
Get();
IdentTypeOptional(out bv);
arguments.Add(bv);
}
- Expect(35);
+ Expect(34);
}
Expect(62);
while (StartOf(10)) {
@@ -1682,7 +1712,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(161);
+ } else SynErr(160);
}
void QuantifierDomain(out List<BoundVar/*!*/> bvars, out Attributes attrs, out Expression range) {
@@ -1693,7 +1723,7 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo IdentTypeOptional(out bv);
bvars.Add(bv);
- while (la.kind == 21) {
+ while (la.kind == 20) {
Get();
IdentTypeOptional(out bv);
bvars.Add(bv);
@@ -1701,7 +1731,7 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo while (la.kind == 6) {
Attribute(ref attrs);
}
- if (la.kind == 18) {
+ if (la.kind == 17) {
Get();
Expression(out range);
}
@@ -1710,7 +1740,7 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo void EquivExpression(out Expression/*!*/ e0) {
Contract.Ensures(Contract.ValueAtReturn(out e0) != null); IToken/*!*/ x; Expression/*!*/ e1;
ImpliesExpression(out e0);
- while (la.kind == 70 || la.kind == 71) {
+ while (la.kind == 69 || la.kind == 70) {
EquivOp();
x = t;
ImpliesExpression(out e1);
@@ -1721,7 +1751,7 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo void ImpliesExpression(out Expression/*!*/ e0) {
Contract.Ensures(Contract.ValueAtReturn(out e0) != null); IToken/*!*/ x; Expression/*!*/ e1;
LogicalExpression(out e0);
- if (la.kind == 72 || la.kind == 73) {
+ if (la.kind == 71 || la.kind == 72) {
ImpliesOp();
x = t;
ImpliesExpression(out e1);
@@ -1730,23 +1760,23 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo }
void EquivOp() {
- if (la.kind == 70) {
+ if (la.kind == 69) {
Get();
- } else if (la.kind == 71) {
+ } else if (la.kind == 70) {
Get();
- } else SynErr(162);
+ } else SynErr(161);
}
void LogicalExpression(out Expression/*!*/ e0) {
Contract.Ensures(Contract.ValueAtReturn(out e0) != null); IToken/*!*/ x; Expression/*!*/ e1;
RelationalExpression(out e0);
if (StartOf(17)) {
- if (la.kind == 74 || la.kind == 75) {
+ if (la.kind == 73 || la.kind == 74) {
AndOp();
x = t;
RelationalExpression(out e1);
e0 = new BinaryExpr(x, BinaryExpr.Opcode.And, e0, e1);
- while (la.kind == 74 || la.kind == 75) {
+ while (la.kind == 73 || la.kind == 74) {
AndOp();
x = t;
RelationalExpression(out e1);
@@ -1757,7 +1787,7 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo x = t;
RelationalExpression(out e1);
e0 = new BinaryExpr(x, BinaryExpr.Opcode.Or, e0, e1);
- while (la.kind == 76 || la.kind == 77) {
+ while (la.kind == 75 || la.kind == 76) {
OrOp();
x = t;
RelationalExpression(out e1);
@@ -1768,11 +1798,11 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo }
void ImpliesOp() {
- if (la.kind == 72) {
+ if (la.kind == 71) {
Get();
- } else if (la.kind == 73) {
+ } else if (la.kind == 72) {
Get();
- } else SynErr(163);
+ } else SynErr(162);
}
void RelationalExpression(out Expression/*!*/ e) {
@@ -1866,25 +1896,25 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo }
void AndOp() {
- if (la.kind == 74) {
+ if (la.kind == 73) {
Get();
- } else if (la.kind == 75) {
+ } else if (la.kind == 74) {
Get();
- } else SynErr(164);
+ } else SynErr(163);
}
void OrOp() {
- if (la.kind == 76) {
+ if (la.kind == 75) {
Get();
- } else if (la.kind == 77) {
+ } else if (la.kind == 76) {
Get();
- } else SynErr(165);
+ } else SynErr(164);
}
void Term(out Expression/*!*/ e0) {
Contract.Ensures(Contract.ValueAtReturn(out e0) != null); IToken/*!*/ x; Expression/*!*/ e1; BinaryExpr.Opcode op;
Factor(out e0);
- while (la.kind == 88 || la.kind == 89) {
+ while (la.kind == 87 || la.kind == 88) {
AddOp(out x, out op);
Factor(out e1);
e0 = new BinaryExpr(x, op, e0, e1);
@@ -1897,50 +1927,50 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo IToken y;
switch (la.kind) {
- case 78: {
+ case 77: {
Get();
x = t; op = BinaryExpr.Opcode.Eq;
break;
}
- case 23: {
+ case 22: {
Get();
x = t; op = BinaryExpr.Opcode.Lt;
break;
}
- case 24: {
+ case 23: {
Get();
x = t; op = BinaryExpr.Opcode.Gt;
break;
}
- case 79: {
+ case 78: {
Get();
x = t; op = BinaryExpr.Opcode.Le;
break;
}
- case 80: {
+ case 79: {
Get();
x = t; op = BinaryExpr.Opcode.Ge;
break;
}
- case 81: {
+ case 80: {
Get();
x = t; op = BinaryExpr.Opcode.Neq;
break;
}
- case 82: {
+ case 81: {
Get();
x = t; op = BinaryExpr.Opcode.Disjoint;
break;
}
- case 83: {
+ case 82: {
Get();
x = t; op = BinaryExpr.Opcode.In;
break;
}
- case 84: {
+ case 83: {
Get();
x = t; y = Token.NoToken;
- if (la.kind == 83) {
+ if (la.kind == 82) {
Get();
y = t;
}
@@ -1955,29 +1985,29 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo break;
}
- case 85: {
+ case 84: {
Get();
x = t; op = BinaryExpr.Opcode.Neq;
break;
}
- case 86: {
+ case 85: {
Get();
x = t; op = BinaryExpr.Opcode.Le;
break;
}
- case 87: {
+ case 86: {
Get();
x = t; op = BinaryExpr.Opcode.Ge;
break;
}
- default: SynErr(166); break;
+ default: SynErr(165); break;
}
}
void Factor(out Expression/*!*/ e0) {
Contract.Ensures(Contract.ValueAtReturn(out e0) != null); IToken/*!*/ x; Expression/*!*/ e1; BinaryExpr.Opcode op;
UnaryExpression(out e0);
- while (la.kind == 47 || la.kind == 90 || la.kind == 91) {
+ while (la.kind == 47 || la.kind == 89 || la.kind == 90) {
MulOp(out x, out op);
UnaryExpression(out e1);
e0 = new BinaryExpr(x, op, e0, e1);
@@ -1986,63 +2016,63 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo void AddOp(out IToken/*!*/ x, out BinaryExpr.Opcode op) {
Contract.Ensures(Contract.ValueAtReturn(out x) != null); x = Token.NoToken; op=BinaryExpr.Opcode.Add/*(dummy)*/;
- if (la.kind == 88) {
+ if (la.kind == 87) {
Get();
x = t; op = BinaryExpr.Opcode.Add;
- } else if (la.kind == 89) {
+ } else if (la.kind == 88) {
Get();
x = t; op = BinaryExpr.Opcode.Sub;
- } else SynErr(167);
+ } else SynErr(166);
}
void UnaryExpression(out Expression/*!*/ e) {
Contract.Ensures(Contract.ValueAtReturn(out e) != null); IToken/*!*/ x; e = dummyExpr;
switch (la.kind) {
- case 89: {
+ case 88: {
Get();
x = t;
UnaryExpression(out e);
e = new BinaryExpr(x, BinaryExpr.Opcode.Sub, new LiteralExpr(x, 0), e);
break;
}
- case 84: case 92: {
+ case 83: case 91: {
NegOp();
x = t;
UnaryExpression(out e);
e = new UnaryExpr(x, UnaryExpr.Opcode.Not, e);
break;
}
- case 20: case 39: case 59: case 65: case 66: case 67: case 102: case 103: case 104: case 105: {
+ case 19: case 38: case 54: case 59: case 65: case 66: case 101: case 102: case 103: case 104: {
EndlessExpression(out e);
break;
}
case 1: {
DottedIdentifiersAndFunction(out e);
- while (la.kind == 55 || la.kind == 57) {
+ while (la.kind == 43 || la.kind == 56) {
Suffix(ref e);
}
break;
}
- case 6: case 55: {
+ case 6: case 56: {
DisplayExpr(out e);
break;
}
- case 40: {
+ case 39: {
MultiSetExpr(out e);
break;
}
- case 42: {
+ case 41: {
MapExpr(out e);
break;
}
- case 2: case 18: case 34: case 93: case 94: case 95: case 96: case 97: case 98: case 99: {
+ case 2: case 17: case 33: case 92: case 93: case 94: case 95: case 96: case 97: case 98: {
ConstAtomExpression(out e);
- while (la.kind == 55 || la.kind == 57) {
+ while (la.kind == 43 || la.kind == 56) {
Suffix(ref e);
}
break;
}
- default: SynErr(168); break;
+ default: SynErr(167); break;
}
}
@@ -2051,21 +2081,21 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo if (la.kind == 47) {
Get();
x = t; op = BinaryExpr.Opcode.Mul;
- } else if (la.kind == 90) {
+ } else if (la.kind == 89) {
Get();
x = t; op = BinaryExpr.Opcode.Div;
- } else if (la.kind == 91) {
+ } else if (la.kind == 90) {
Get();
x = t; op = BinaryExpr.Opcode.Mod;
- } else SynErr(169);
+ } else SynErr(168);
}
void NegOp() {
- if (la.kind == 84) {
+ if (la.kind == 83) {
Get();
- } else if (la.kind == 92) {
+ } else if (la.kind == 91) {
Get();
- } else SynErr(170);
+ } else SynErr(169);
}
void EndlessExpression(out Expression e) {
@@ -2080,7 +2110,7 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo Get();
x = t;
Expression(out e);
- Expect(100);
+ Expect(99);
Expression(out e0);
Expect(60);
Expression(out e1);
@@ -2091,11 +2121,11 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo MatchExpression(out e);
break;
}
- case 102: case 103: case 104: case 105: {
+ case 101: case 102: case 103: case 104: {
QuantifierGuts(out e);
break;
}
- case 39: {
+ case 38: {
ComprehensionExpr(out e);
break;
}
@@ -2103,28 +2133,28 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo Get();
x = t;
Expression(out e0);
- Expect(19);
+ Expect(18);
Expression(out e1);
e = new AssertExpr(x, e0, e1);
break;
}
- case 67: {
+ case 54: {
Get();
x = t;
Expression(out e0);
- Expect(19);
+ Expect(18);
Expression(out e1);
e = new AssumeExpr(x, e0, e1);
break;
}
- case 20: {
+ case 19: {
Get();
x = t;
letVars = new List<BoundVar>();
letRHSs = new List<Expression>();
IdentTypeOptional(out d);
letVars.Add(d);
- while (la.kind == 21) {
+ while (la.kind == 20) {
Get();
IdentTypeOptional(out d);
letVars.Add(d);
@@ -2132,17 +2162,17 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo Expect(52);
Expression(out e);
letRHSs.Add(e);
- while (la.kind == 21) {
+ while (la.kind == 20) {
Get();
Expression(out e);
letRHSs.Add(e);
}
- Expect(19);
+ Expect(18);
Expression(out e);
e = new LetExpr(x, letVars, letRHSs, e);
break;
}
- default: SynErr(171); break;
+ default: SynErr(170); break;
}
}
@@ -2153,18 +2183,18 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo Ident(out id);
idents.Add(id);
- while (la.kind == 57) {
+ while (la.kind == 43) {
Get();
Ident(out id);
idents.Add(id);
}
- if (la.kind == 34) {
+ if (la.kind == 33) {
Get();
openParen = t; args = new List<Expression>();
if (StartOf(9)) {
Expressions(args);
}
- Expect(35);
+ Expect(34);
}
e = new IdentifierSequence(idents, openParen, args);
}
@@ -2175,26 +2205,26 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo List<Expression> multipleIndices = null;
bool func = false;
- if (la.kind == 57) {
+ if (la.kind == 43) {
Get();
Ident(out id);
- if (la.kind == 34) {
+ if (la.kind == 33) {
Get();
IToken openParen = t; args = new List<Expression/*!*/>(); func = true;
if (StartOf(9)) {
Expressions(args);
}
- Expect(35);
+ Expect(34);
e = new FunctionCallExpr(id, id.val, e, openParen, args);
}
if (!func) { e = new ExprDotName(id, e, id.val); }
- } else if (la.kind == 55) {
+ } else if (la.kind == 56) {
Get();
x = t;
if (StartOf(9)) {
Expression(out ee);
e0 = ee;
- if (la.kind == 101) {
+ if (la.kind == 100) {
Get();
anyDots = true;
if (StartOf(9)) {
@@ -2205,8 +2235,8 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo Get();
Expression(out ee);
e1 = ee;
- } else if (la.kind == 21 || la.kind == 56) {
- while (la.kind == 21) {
+ } else if (la.kind == 20 || la.kind == 57) {
+ while (la.kind == 20) {
Get();
Expression(out ee);
if (multipleIndices == null) {
@@ -2216,15 +2246,15 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo multipleIndices.Add(ee);
}
- } else SynErr(172);
- } else if (la.kind == 101) {
+ } else SynErr(171);
+ } else if (la.kind == 100) {
Get();
anyDots = true;
if (StartOf(9)) {
Expression(out ee);
e1 = ee;
}
- } else SynErr(173);
+ } else SynErr(172);
if (multipleIndices != null) {
e = new MultiSelectExpr(x, e, multipleIndices);
// make sure an array class with this dimensionality exists
@@ -2247,8 +2277,8 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo }
}
- Expect(56);
- } else SynErr(174);
+ Expect(57);
+ } else SynErr(173);
}
void DisplayExpr(out Expression e) {
@@ -2264,15 +2294,15 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo }
e = new SetDisplayExpr(x, elements);
Expect(7);
- } else if (la.kind == 55) {
+ } else if (la.kind == 56) {
Get();
x = t; elements = new List<Expression/*!*/>();
if (StartOf(9)) {
Expressions(elements);
}
e = new SeqDisplayExpr(x, elements);
- Expect(56);
- } else SynErr(175);
+ Expect(57);
+ } else SynErr(174);
}
void MultiSetExpr(out Expression e) {
@@ -2280,7 +2310,7 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo IToken/*!*/ x = null; List<Expression/*!*/>/*!*/ elements;
e = dummyExpr;
- Expect(40);
+ Expect(39);
x = t;
if (la.kind == 6) {
Get();
@@ -2290,15 +2320,15 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo }
e = new MultiSetDisplayExpr(x, elements);
Expect(7);
- } else if (la.kind == 34) {
+ } else if (la.kind == 33) {
Get();
x = t; elements = new List<Expression/*!*/>();
Expression(out e);
e = new MultiSetFormingExpr(x, e);
- Expect(35);
+ Expect(34);
} else if (StartOf(19)) {
SemErr("multiset must be followed by multiset literal or expression to coerce in parentheses.");
- } else SynErr(176);
+ } else SynErr(175);
}
void MapExpr(out Expression e) {
@@ -2307,16 +2337,16 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo List<ExpressionPair/*!*/>/*!*/ elements;
e = dummyExpr;
- Expect(42);
+ Expect(41);
x = t;
- if (la.kind == 55) {
+ if (la.kind == 56) {
Get();
elements = new List<ExpressionPair/*!*/>();
if (StartOf(9)) {
MapLiteralExpressions(out elements);
}
e = new MapDisplayExpr(x, elements);
- Expect(56);
+ Expect(57);
} else if (la.kind == 1) {
BoundVar/*!*/ bv;
List<BoundVar/*!*/> bvars = new List<BoundVar/*!*/>();
@@ -2325,14 +2355,14 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo IdentTypeOptional(out bv);
bvars.Add(bv);
- Expect(18);
+ Expect(17);
Expression(out range);
QSep();
Expression(out body);
e = new MapComprehension(x, bvars, range, body);
} else if (StartOf(19)) {
SemErr("map must be followed by literal in brackets or comprehension.");
- } else SynErr(177);
+ } else SynErr(176);
}
void ConstAtomExpression(out Expression/*!*/ e) {
@@ -2341,17 +2371,17 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo e = dummyExpr;
switch (la.kind) {
- case 93: {
+ case 92: {
Get();
e = new LiteralExpr(t, false);
break;
}
- case 94: {
+ case 93: {
Get();
e = new LiteralExpr(t, true);
break;
}
- case 95: {
+ case 94: {
Get();
e = new LiteralExpr(t);
break;
@@ -2361,55 +2391,55 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo e = new LiteralExpr(t, n);
break;
}
- case 96: {
+ case 95: {
Get();
e = new ThisExpr(t);
break;
}
- case 97: {
+ case 96: {
Get();
x = t;
- Expect(34);
+ Expect(33);
Expression(out e);
- Expect(35);
+ Expect(34);
e = new FreshExpr(x, e);
break;
}
- case 98: {
+ case 97: {
Get();
x = t;
- Expect(34);
+ Expect(33);
Expression(out e);
- Expect(35);
+ Expect(34);
e = new AllocatedExpr(x, e);
break;
}
- case 99: {
+ case 98: {
Get();
x = t;
- Expect(34);
+ Expect(33);
Expression(out e);
- Expect(35);
+ Expect(34);
e = new OldExpr(x, e);
break;
}
- case 18: {
+ case 17: {
Get();
x = t;
Expression(out e);
e = new UnaryExpr(x, UnaryExpr.Opcode.SeqLength, e);
- Expect(18);
+ Expect(17);
break;
}
- case 34: {
+ case 33: {
Get();
x = t;
Expression(out e);
e = new ParensExpression(x, e);
- Expect(35);
+ Expect(34);
break;
}
- default: SynErr(178); break;
+ default: SynErr(177); break;
}
}
@@ -2431,7 +2461,7 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo Expect(52);
Expression(out r);
elements.Add(new ExpressionPair(d,r));
- while (la.kind == 21) {
+ while (la.kind == 20) {
Get();
Expression(out d);
Expect(52);
@@ -2441,11 +2471,11 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo }
void QSep() {
- if (la.kind == 106) {
+ if (la.kind == 105) {
Get();
- } else if (la.kind == 107) {
+ } else if (la.kind == 106) {
Get();
- } else SynErr(179);
+ } else SynErr(178);
}
void MatchExpression(out Expression/*!*/ e) {
@@ -2470,13 +2500,13 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo Expression range;
Expression/*!*/ body;
- if (la.kind == 102 || la.kind == 103) {
+ if (la.kind == 101 || la.kind == 102) {
Forall();
x = t; univ = true;
- } else if (la.kind == 104 || la.kind == 105) {
+ } else if (la.kind == 103 || la.kind == 104) {
Exists();
x = t;
- } else SynErr(180);
+ } else SynErr(179);
QuantifierDomain(out bvars, out attrs, out range);
QSep();
Expression(out body);
@@ -2496,18 +2526,18 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo Expression/*!*/ range;
Expression body = null;
- Expect(39);
+ Expect(38);
x = t;
IdentTypeOptional(out bv);
bvars.Add(bv);
- while (la.kind == 21) {
+ while (la.kind == 20) {
Get();
IdentTypeOptional(out bv);
bvars.Add(bv);
}
- Expect(18);
+ Expect(17);
Expression(out range);
- if (la.kind == 106 || la.kind == 107) {
+ if (la.kind == 105 || la.kind == 106) {
QSep();
Expression(out body);
}
@@ -2525,16 +2555,16 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo Expect(61);
x = t;
Ident(out id);
- if (la.kind == 34) {
+ if (la.kind == 33) {
Get();
IdentTypeOptional(out bv);
arguments.Add(bv);
- while (la.kind == 21) {
+ while (la.kind == 20) {
Get();
IdentTypeOptional(out bv);
arguments.Add(bv);
}
- Expect(35);
+ Expect(34);
}
Expect(62);
Expression(out body);
@@ -2542,19 +2572,19 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo }
void Forall() {
- if (la.kind == 102) {
+ if (la.kind == 101) {
Get();
- } else if (la.kind == 103) {
+ } else if (la.kind == 102) {
Get();
- } else SynErr(181);
+ } else SynErr(180);
}
void Exists() {
- if (la.kind == 104) {
+ if (la.kind == 103) {
Get();
- } else if (la.kind == 105) {
+ } else if (la.kind == 104) {
Get();
- } else SynErr(182);
+ } else SynErr(181);
}
void AttributeBody(ref Attributes attrs) {
@@ -2568,7 +2598,7 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo if (StartOf(20)) {
AttributeArg(out aArg);
aArgs.Add(aArg);
- while (la.kind == 21) {
+ while (la.kind == 20) {
Get();
AttributeArg(out aArg);
aArgs.Add(aArg);
@@ -2590,27 +2620,27 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo }
static readonly bool[,]/*!*/ set = {
- {T,T,T,x, x,x,T,x, T,x,x,x, T,x,x,T, 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, x,T,T,T, x,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, 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,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, T,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,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, T,x,x,x, x,T,T,x, 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,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},
- {T,x,x,x, x,x,T,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,x, T,T,T,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x},
- {x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,T, T,T,x,x, x,x,x,x, x,x,x,x, x,x,T,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x},
- {x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,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,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,x, T,T,T,T, T,T,T,T, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,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,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,x},
- {x,T,T,x, x,x,T,x, 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,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, T,x,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, x,T,T,T, x,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,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,T,x, x,x,x,T, 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},
- {T,T,T,x, x,x,T,x, T,x,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, x,T,T,T, x,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, 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,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,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,T,x, x,x,x,T, x,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,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,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,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,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,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,T,T, T,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x},
- {x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,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,T,T, T,T,T,T, T,T,T,T, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x},
- {x,x,x,x, x,x,T,T, x,x,x,x, x,x,x,x, x,x,T,T, x,T,x,T, T,x,x,x, x,x,x,x, x,x,x,T, x,x,x,x, x,x,x,x, x,x,x,T, T,x,x,x, T,x,x,x, T,x,x,x, T,T,T,x, x,x,x,x, x,x,T,T, T,T,T,T, T,T,T,T, T,T,T,T, T,T,T,T, T,T,T,T, x,x,x,x, x,x,x,x, T,T,x,x, x,x,T,T, x,x},
- {x,T,T,x, T,x,T,x, 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,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}
+ {T,T,T,x, x,x,T,x, T,x,x,x, T,x,T,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,x, x,T,T,T, x,x,T,x, x,x,x,T, x,x,x,T, T,T,T,T, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, 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,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,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,x,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,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,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, 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, 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,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,x,x, 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, 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,T,x,x, x,x,x,x, x,x,x,x, x,x,T,x, T,x,x,T, x,x,x,x, x,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, 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,x, x,T,T,T, x,x,T,x, x,x,x,T, x,x,x,T, x,T,T,T, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, 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,T,x,x, x,x,x,T, x,x,x,x, x,x,T,x, T,x,x,T, x,x,x,x, x,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, 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,x, x,T,T,T, x,x,T,x, x,x,x,T, x,x,x,T, x,T,T,T, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, 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,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,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,T,x,x, x,x,x,T, x,x,x,x, x,x,T,T, T,x,T,T, x,x,x,x, x,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,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, 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,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,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,T,T,T, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x},
+ {x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,T,T, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,T,T,T, T,T,T,T, T,T,T,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x},
+ {x,x,x,x, x,x,T,T, x,x,x,x, x,x,x,x, x,T,T,x, T,x,T,T, x,x,x,x, x,x,x,x, x,x,T,x, x,x,x,x, x,x,x,x, x,x,x,T, T,x,x,x, T,x,x,x, x,T,x,x, T,T,T,x, x,x,x,x, x,T,T,T, T,T,T,T, T,T,T,T, T,T,T,T, T,T,T,T, T,T,T,x, x,x,x,x, x,x,x,T, T,x,x,x, x,T,T,x, x},
+ {x,T,T,x, T,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,T,x,x, x,x,x,x, x,x,x,x, x,x,T,x, T,x,x,T, x,x,x,x, x,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}
};
} // end Parser
@@ -2649,36 +2679,36 @@ public class Errors { 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;
- case 16: s = "\"codatatype\" expected"; break;
- case 17: s = "\"=\" expected"; break;
- case 18: s = "\"|\" expected"; break;
- case 19: s = "\";\" expected"; break;
- case 20: s = "\"var\" expected"; break;
- case 21: s = "\",\" expected"; break;
- case 22: s = "\"type\" expected"; break;
- case 23: s = "\"<\" expected"; break;
- case 24: s = "\">\" expected"; break;
- case 25: s = "\"method\" expected"; break;
- case 26: s = "\"constructor\" expected"; break;
- case 27: s = "\"returns\" expected"; break;
- case 28: s = "\"...\" expected"; break;
- case 29: s = "\"modifies\" expected"; break;
- case 30: s = "\"free\" expected"; break;
- case 31: s = "\"requires\" expected"; break;
- case 32: s = "\"ensures\" expected"; break;
- case 33: s = "\"decreases\" expected"; break;
- case 34: s = "\"(\" expected"; break;
- case 35: s = "\")\" expected"; break;
- case 36: s = "\"bool\" expected"; break;
- case 37: s = "\"nat\" expected"; break;
- case 38: s = "\"int\" expected"; break;
- case 39: s = "\"set\" expected"; break;
- case 40: s = "\"multiset\" expected"; break;
- case 41: s = "\"seq\" expected"; break;
- case 42: s = "\"map\" expected"; break;
- case 43: s = "\"object\" expected"; break;
+ case 14: s = "\"datatype\" expected"; break;
+ case 15: s = "\"codatatype\" expected"; break;
+ case 16: s = "\"=\" expected"; break;
+ case 17: s = "\"|\" expected"; break;
+ case 18: s = "\";\" expected"; break;
+ case 19: s = "\"var\" expected"; break;
+ case 20: s = "\",\" expected"; break;
+ case 21: s = "\"type\" expected"; break;
+ case 22: s = "\"<\" expected"; break;
+ case 23: s = "\">\" expected"; break;
+ case 24: s = "\"method\" expected"; break;
+ case 25: s = "\"constructor\" expected"; break;
+ case 26: s = "\"returns\" expected"; break;
+ case 27: s = "\"...\" expected"; break;
+ case 28: s = "\"modifies\" expected"; break;
+ case 29: s = "\"free\" expected"; break;
+ case 30: s = "\"requires\" expected"; break;
+ case 31: s = "\"ensures\" expected"; break;
+ case 32: s = "\"decreases\" expected"; break;
+ case 33: s = "\"(\" expected"; break;
+ case 34: s = "\")\" expected"; break;
+ case 35: s = "\"bool\" expected"; break;
+ case 36: s = "\"nat\" expected"; break;
+ case 37: s = "\"int\" expected"; break;
+ case 38: s = "\"set\" expected"; break;
+ case 39: s = "\"multiset\" expected"; break;
+ case 40: s = "\"seq\" expected"; break;
+ case 41: s = "\"map\" expected"; break;
+ case 42: s = "\"object\" expected"; break;
+ case 43: s = "\".\" expected"; break;
case 44: s = "\"function\" expected"; break;
case 45: s = "\"predicate\" expected"; break;
case 46: s = "\"reads\" expected"; break;
@@ -2689,10 +2719,10 @@ public class Errors { case 51: s = "\"return\" expected"; break;
case 52: s = "\":=\" expected"; break;
case 53: s = "\":|\" expected"; break;
- case 54: s = "\"new\" expected"; break;
- case 55: s = "\"[\" expected"; break;
- case 56: s = "\"]\" expected"; break;
- case 57: s = "\".\" expected"; break;
+ case 54: s = "\"assume\" expected"; break;
+ case 55: s = "\"new\" expected"; break;
+ case 56: s = "\"[\" expected"; break;
+ case 57: s = "\"]\" expected"; break;
case 58: s = "\"choose\" expected"; break;
case 59: s = "\"if\" expected"; break;
case 60: s = "\"else\" expected"; break;
@@ -2702,122 +2732,121 @@ public class Errors { case 64: s = "\"invariant\" expected"; break;
case 65: s = "\"match\" expected"; break;
case 66: s = "\"assert\" expected"; break;
- case 67: s = "\"assume\" expected"; break;
- case 68: s = "\"print\" expected"; break;
- case 69: s = "\"parallel\" expected"; break;
- case 70: s = "\"<==>\" expected"; break;
- case 71: s = "\"\\u21d4\" expected"; break;
- case 72: s = "\"==>\" expected"; break;
- case 73: s = "\"\\u21d2\" expected"; break;
- case 74: s = "\"&&\" expected"; break;
- case 75: s = "\"\\u2227\" expected"; break;
- case 76: s = "\"||\" expected"; break;
- case 77: s = "\"\\u2228\" expected"; break;
- case 78: s = "\"==\" expected"; break;
- case 79: s = "\"<=\" expected"; break;
- case 80: s = "\">=\" expected"; break;
- case 81: s = "\"!=\" expected"; break;
- case 82: s = "\"!!\" expected"; break;
- case 83: s = "\"in\" expected"; break;
- case 84: s = "\"!\" expected"; break;
- case 85: s = "\"\\u2260\" expected"; break;
- case 86: s = "\"\\u2264\" expected"; break;
- case 87: s = "\"\\u2265\" expected"; break;
- case 88: s = "\"+\" expected"; break;
- case 89: s = "\"-\" expected"; break;
- case 90: s = "\"/\" expected"; break;
- case 91: s = "\"%\" expected"; break;
- case 92: s = "\"\\u00ac\" expected"; break;
- case 93: s = "\"false\" expected"; break;
- case 94: s = "\"true\" expected"; break;
- case 95: s = "\"null\" expected"; break;
- case 96: s = "\"this\" expected"; break;
- case 97: s = "\"fresh\" expected"; break;
- case 98: s = "\"allocated\" expected"; break;
- case 99: s = "\"old\" expected"; break;
- case 100: s = "\"then\" expected"; break;
- case 101: s = "\"..\" expected"; break;
- case 102: s = "\"forall\" expected"; break;
- case 103: s = "\"\\u2200\" expected"; break;
- case 104: s = "\"exists\" expected"; break;
- case 105: s = "\"\\u2203\" expected"; break;
- case 106: s = "\"::\" expected"; break;
- case 107: s = "\"\\u2022\" expected"; break;
- case 108: s = "??? expected"; break;
- case 109: s = "invalid Dafny"; break;
- case 110: s = "this symbol not expected in ClassDecl"; break;
- case 111: s = "this symbol not expected in DatatypeDecl"; break;
- case 112: s = "invalid DatatypeDecl"; break;
- case 113: s = "this symbol not expected in DatatypeDecl"; break;
- case 114: s = "this symbol not expected in ArbitraryTypeDecl"; break;
- case 115: s = "invalid ClassMemberDecl"; break;
+ case 67: s = "\"print\" expected"; break;
+ case 68: s = "\"parallel\" expected"; break;
+ case 69: s = "\"<==>\" expected"; break;
+ case 70: s = "\"\\u21d4\" expected"; break;
+ case 71: s = "\"==>\" expected"; break;
+ case 72: s = "\"\\u21d2\" expected"; break;
+ case 73: s = "\"&&\" expected"; break;
+ case 74: s = "\"\\u2227\" expected"; break;
+ case 75: s = "\"||\" expected"; break;
+ case 76: s = "\"\\u2228\" expected"; break;
+ case 77: s = "\"==\" expected"; break;
+ case 78: s = "\"<=\" expected"; break;
+ case 79: s = "\">=\" expected"; break;
+ case 80: s = "\"!=\" expected"; break;
+ case 81: s = "\"!!\" expected"; break;
+ case 82: s = "\"in\" expected"; break;
+ case 83: s = "\"!\" expected"; break;
+ case 84: s = "\"\\u2260\" expected"; break;
+ case 85: s = "\"\\u2264\" expected"; break;
+ case 86: s = "\"\\u2265\" expected"; break;
+ case 87: s = "\"+\" expected"; break;
+ case 88: s = "\"-\" expected"; break;
+ case 89: s = "\"/\" expected"; break;
+ case 90: s = "\"%\" expected"; break;
+ case 91: s = "\"\\u00ac\" expected"; break;
+ case 92: s = "\"false\" expected"; break;
+ case 93: s = "\"true\" expected"; break;
+ case 94: s = "\"null\" expected"; break;
+ case 95: s = "\"this\" expected"; break;
+ case 96: s = "\"fresh\" expected"; break;
+ case 97: s = "\"allocated\" expected"; break;
+ case 98: s = "\"old\" expected"; break;
+ case 99: s = "\"then\" expected"; break;
+ case 100: s = "\"..\" expected"; break;
+ case 101: s = "\"forall\" expected"; break;
+ case 102: s = "\"\\u2200\" expected"; break;
+ case 103: s = "\"exists\" expected"; break;
+ case 104: s = "\"\\u2203\" expected"; break;
+ case 105: s = "\"::\" expected"; break;
+ case 106: s = "\"\\u2022\" expected"; break;
+ case 107: s = "??? expected"; break;
+ case 108: s = "invalid Dafny"; break;
+ case 109: s = "this symbol not expected in ClassDecl"; break;
+ case 110: s = "this symbol not expected in DatatypeDecl"; break;
+ case 111: s = "invalid DatatypeDecl"; break;
+ case 112: s = "this symbol not expected in DatatypeDecl"; break;
+ case 113: s = "this symbol not expected in ArbitraryTypeDecl"; break;
+ case 114: s = "invalid ClassMemberDecl"; break;
+ case 115: s = "this symbol not expected in FieldDecl"; break;
case 116: s = "this symbol not expected in FieldDecl"; break;
- case 117: s = "this symbol not expected in FieldDecl"; break;
+ case 117: s = "invalid FunctionDecl"; break;
case 118: s = "invalid FunctionDecl"; break;
case 119: s = "invalid FunctionDecl"; break;
- case 120: s = "invalid FunctionDecl"; break;
- case 121: s = "this symbol not expected in MethodDecl"; break;
+ case 120: s = "this symbol not expected in MethodDecl"; break;
+ case 121: s = "invalid MethodDecl"; break;
case 122: s = "invalid MethodDecl"; break;
- case 123: s = "invalid MethodDecl"; break;
- case 124: s = "invalid TypeAndToken"; break;
+ case 123: s = "invalid TypeAndToken"; break;
+ case 124: s = "this symbol not expected in MethodSpec"; break;
case 125: s = "this symbol not expected in MethodSpec"; break;
case 126: s = "this symbol not expected in MethodSpec"; break;
case 127: s = "this symbol not expected in MethodSpec"; break;
- case 128: s = "this symbol not expected in MethodSpec"; break;
- case 129: s = "invalid MethodSpec"; break;
- case 130: s = "this symbol not expected in MethodSpec"; break;
- case 131: s = "invalid MethodSpec"; break;
- case 132: s = "invalid ReferenceType"; break;
+ case 128: s = "invalid MethodSpec"; break;
+ case 129: s = "this symbol not expected in MethodSpec"; break;
+ case 130: s = "invalid MethodSpec"; break;
+ case 131: s = "invalid ReferenceType"; break;
+ case 132: s = "this symbol not expected in FunctionSpec"; break;
case 133: s = "this symbol not expected in FunctionSpec"; break;
case 134: s = "this symbol not expected in FunctionSpec"; break;
case 135: s = "this symbol not expected in FunctionSpec"; break;
case 136: s = "this symbol not expected in FunctionSpec"; break;
- case 137: s = "this symbol not expected in FunctionSpec"; break;
- case 138: s = "invalid FunctionSpec"; break;
- case 139: s = "invalid PossiblyWildFrameExpression"; break;
- case 140: s = "invalid PossiblyWildExpression"; break;
- case 141: s = "this symbol not expected in OneStmt"; break;
- case 142: s = "invalid OneStmt"; break;
- case 143: s = "this symbol not expected in OneStmt"; break;
- case 144: s = "invalid OneStmt"; break;
- case 145: s = "invalid AssertStmt"; break;
+ case 137: s = "invalid FunctionSpec"; break;
+ case 138: s = "invalid PossiblyWildFrameExpression"; break;
+ case 139: s = "invalid PossiblyWildExpression"; break;
+ case 140: s = "this symbol not expected in OneStmt"; break;
+ case 141: s = "invalid OneStmt"; break;
+ case 142: s = "this symbol not expected in OneStmt"; break;
+ case 143: s = "invalid OneStmt"; break;
+ case 144: s = "invalid AssertStmt"; break;
+ case 145: s = "invalid UpdateStmt"; break;
case 146: s = "invalid UpdateStmt"; break;
- case 147: s = "invalid UpdateStmt"; break;
+ case 147: s = "invalid IfStmt"; break;
case 148: s = "invalid IfStmt"; break;
- case 149: s = "invalid IfStmt"; break;
+ case 149: s = "invalid WhileStmt"; break;
case 150: s = "invalid WhileStmt"; break;
- case 151: s = "invalid WhileStmt"; break;
- case 152: s = "invalid Rhs"; break;
- case 153: s = "invalid Lhs"; break;
- case 154: s = "invalid Guard"; break;
+ case 151: s = "invalid Rhs"; break;
+ case 152: s = "invalid Lhs"; break;
+ case 153: s = "invalid Guard"; break;
+ case 154: s = "this symbol not expected in LoopSpec"; break;
case 155: s = "this symbol not expected in LoopSpec"; break;
case 156: s = "this symbol not expected in LoopSpec"; break;
case 157: s = "this symbol not expected in LoopSpec"; break;
case 158: s = "this symbol not expected in LoopSpec"; break;
- case 159: s = "this symbol not expected in LoopSpec"; break;
- case 160: s = "this symbol not expected in Invariant"; break;
- case 161: s = "invalid AttributeArg"; break;
- case 162: s = "invalid EquivOp"; break;
- case 163: s = "invalid ImpliesOp"; break;
- case 164: s = "invalid AndOp"; break;
- case 165: s = "invalid OrOp"; break;
- case 166: s = "invalid RelOp"; break;
- case 167: s = "invalid AddOp"; break;
- case 168: s = "invalid UnaryExpression"; break;
- case 169: s = "invalid MulOp"; break;
- case 170: s = "invalid NegOp"; break;
- case 171: s = "invalid EndlessExpression"; break;
+ case 159: s = "this symbol not expected in Invariant"; break;
+ case 160: s = "invalid AttributeArg"; break;
+ case 161: s = "invalid EquivOp"; break;
+ case 162: s = "invalid ImpliesOp"; break;
+ case 163: s = "invalid AndOp"; break;
+ case 164: s = "invalid OrOp"; break;
+ case 165: s = "invalid RelOp"; break;
+ case 166: s = "invalid AddOp"; break;
+ case 167: s = "invalid UnaryExpression"; break;
+ case 168: s = "invalid MulOp"; break;
+ case 169: s = "invalid NegOp"; break;
+ case 170: s = "invalid EndlessExpression"; break;
+ case 171: s = "invalid Suffix"; break;
case 172: s = "invalid Suffix"; break;
case 173: s = "invalid Suffix"; break;
- case 174: s = "invalid Suffix"; break;
- case 175: s = "invalid DisplayExpr"; break;
- case 176: s = "invalid MultiSetExpr"; break;
- case 177: s = "invalid MapExpr"; break;
- case 178: s = "invalid ConstAtomExpression"; break;
- case 179: s = "invalid QSep"; break;
- case 180: s = "invalid QuantifierGuts"; break;
- case 181: s = "invalid Forall"; break;
- case 182: s = "invalid Exists"; break;
+ case 174: s = "invalid DisplayExpr"; break;
+ case 175: s = "invalid MultiSetExpr"; break;
+ case 176: s = "invalid MapExpr"; break;
+ case 177: s = "invalid ConstAtomExpression"; break;
+ case 178: s = "invalid QSep"; break;
+ case 179: s = "invalid QuantifierGuts"; break;
+ case 180: s = "invalid Forall"; break;
+ case 181: s = "invalid Exists"; break;
default: s = "error " + n; break;
}
diff --git a/Source/Dafny/Printer.cs b/Source/Dafny/Printer.cs index 6cf71fa1..fb46ba4b 100644 --- a/Source/Dafny/Printer.cs +++ b/Source/Dafny/Printer.cs @@ -222,7 +222,6 @@ namespace Microsoft.Dafny { var isPredicate = f is Predicate;
Indent(indent);
string k = isPredicate ? "predicate" : "function";
- if (f.IsUnlimited) { k = "unlimited " + k; }
if (f.IsStatic) { k = "static " + k; }
if (!f.IsGhost) { k += " method"; }
PrintClassMethodHelper(k, f.Attributes, f.Name, f.TypeArgs);
@@ -421,9 +420,9 @@ namespace Microsoft.Dafny { /// </summary>
public void PrintStatement(Statement stmt, int indent) {
Contract.Requires(stmt != null);
- for (LabelNode label = stmt.Labels; label != null; label = label.Next) {
- if (label.Label != null) {
- wr.WriteLine("label {0}:", label.Label);
+ for (LList<Label> label = stmt.Labels; label != null; label = label.Next) {
+ if (label.Data.Name != null) {
+ wr.WriteLine("label {0}:", label.Data.Name);
Indent(indent);
}
}
@@ -662,7 +661,10 @@ namespace Microsoft.Dafny { } else if (s is AssignSuchThatStmt) {
var update = (AssignSuchThatStmt)s;
wr.Write(" :| ");
- PrintExpression(update.Assume.Expr);
+ if (update.AssumeToken != null) {
+ wr.Write("assume ");
+ }
+ PrintExpression(update.Expr);
} else {
Contract.Assert(s == null); // otherwise, unknown type
}
diff --git a/Source/Dafny/RefinementTransformer.cs b/Source/Dafny/RefinementTransformer.cs index d966a76f..51b22443 100644 --- a/Source/Dafny/RefinementTransformer.cs +++ b/Source/Dafny/RefinementTransformer.cs @@ -186,19 +186,19 @@ namespace Microsoft.Dafny { return t;
} else if (t is SetType) {
var tt = (SetType)t;
- return new SetType(tt.Arg);
+ return new SetType(CloneType(tt.Arg));
} else if (t is SeqType) {
var tt = (SeqType)t;
- return new SeqType(tt.Arg);
+ return new SeqType(CloneType(tt.Arg));
} else if (t is MultiSetType) {
var tt = (MultiSetType)t;
- return new MultiSetType(tt.Arg);
+ return new MultiSetType(CloneType(tt.Arg));
} else if (t is MapType) {
var tt = (MapType)t;
- return new MapType(tt.Domain, tt.Range);
+ return new MapType(CloneType(tt.Domain), CloneType(tt.Range));
} else if (t is UserDefinedType) {
var tt = (UserDefinedType)t;
- return new UserDefinedType(Tok(tt.tok), tt.Name, tt.TypeArgs.ConvertAll(CloneType));
+ return new UserDefinedType(Tok(tt.tok), tt.Name, tt.TypeArgs.ConvertAll(CloneType), tt.ModuleName == null ? null : Tok(tt.ModuleName));
} else if (t is InferredTypeProxy) {
return new InferredTypeProxy();
} else {
@@ -493,7 +493,7 @@ namespace Microsoft.Dafny { } else if (stmt is AssignSuchThatStmt) {
var s = (AssignSuchThatStmt)stmt;
- r = new AssignSuchThatStmt(Tok(s.Tok), s.Lhss.ConvertAll(CloneExpr), CloneExpr(s.Assume.Expr));
+ r = new AssignSuchThatStmt(Tok(s.Tok), s.Lhss.ConvertAll(CloneExpr), CloneExpr(s.Expr), s.AssumeToken == null ? null : Tok(s.AssumeToken));
} else if (stmt is UpdateStmt) {
var s = (UpdateStmt)stmt;
@@ -513,13 +513,13 @@ namespace Microsoft.Dafny { return r;
}
- void AddStmtLabels(Statement s, LabelNode node) {
+ void AddStmtLabels(Statement s, LList<Label> node) {
if (node != null) {
AddStmtLabels(s, node.Next);
- if (node.Label == null) {
+ if (node.Data.Name == 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);
+ s.Labels = new LList<Label>(new Label(Tok(node.Data.Tok), node.Data.Name), s.Labels);
}
}
}
@@ -560,10 +560,10 @@ namespace Microsoft.Dafny { }
if (f is Predicate) {
- return new Predicate(tok, f.Name, f.IsStatic, isGhost, f.IsUnlimited, tps, f.OpenParen, formals,
+ return new Predicate(tok, f.Name, f.IsStatic, isGhost, tps, f.OpenParen, formals,
req, reads, ens, decreases, body, moreBody != null, null, false);
} else {
- return new Function(tok, f.Name, f.IsStatic, isGhost, f.IsUnlimited, tps, f.OpenParen, formals, CloneType(f.ResultType),
+ return new Function(tok, f.Name, f.IsStatic, isGhost, tps, f.OpenParen, formals, CloneType(f.ResultType),
req, reads, ens, decreases, body, null, false);
}
}
@@ -638,9 +638,6 @@ namespace Microsoft.Dafny { if (prevFunction.IsStatic != f.IsStatic) {
reporter.Error(f, "a function in a refining module cannot be changed from static to non-static or vice versa: {0}", f.Name);
}
- if (prevFunction.IsUnlimited != f.IsUnlimited) {
- reporter.Error(f, "a function in a refining module cannot be changed from unlimited to limited or vice versa: {0}", f.Name);
- }
if (!prevFunction.IsGhost && f.IsGhost) {
reporter.Error(f, "a function method cannot be changed into a (ghost) function in a refining module: {0}", f.Name);
} else if (prevFunction.IsGhost && !f.IsGhost && prevFunction.Body != null) {
@@ -917,7 +914,7 @@ namespace Microsoft.Dafny { doMerge = true;
} else if (cOld.Update is AssignSuchThatStmt) {
doMerge = true;
- addedAssert = CloneExpr(((AssignSuchThatStmt)cOld.Update).Assume.Expr);
+ addedAssert = CloneExpr(((AssignSuchThatStmt)cOld.Update).Expr);
} else {
var updateOld = (UpdateStmt)cOld.Update; // if cast fails, there are more ConcreteUpdateStatement subclasses than expected
if (updateOld.Rhss.Count == 1 && updateOld.Rhss[0] is HavocRhs) {
@@ -1090,8 +1087,8 @@ namespace Microsoft.Dafny { Contract.Requires(labels != null);
Contract.Requires(0 <= loopLevels);
- for (LabelNode n = s.Labels; n != null; n = n.Next) {
- labels.Push(n.Label);
+ for (LList<Label> n = s.Labels; n != null; n = n.Next) {
+ labels.Push(n.Data.Name);
}
if (s is SkeletonStatement) {
@@ -1116,7 +1113,7 @@ namespace Microsoft.Dafny { }
}
- for (LabelNode n = s.Labels; n != null; n = n.Next) {
+ for (LList<Label> n = s.Labels; n != null; n = n.Next) {
labels.Pop();
}
}
diff --git a/Source/Dafny/Resolver.cs b/Source/Dafny/Resolver.cs index 7be3fca2..f0990aa0 100644 --- a/Source/Dafny/Resolver.cs +++ b/Source/Dafny/Resolver.cs @@ -322,7 +322,7 @@ namespace Microsoft.Dafny { // create and add the query "method" (field, really)
string queryName = ctor.Name + "?";
- var query = new SpecialField(ctor.tok, queryName, "_" + ctor.Name, "", "", false, false, Type.Bool, null);
+ var query = new SpecialField(ctor.tok, queryName, "is_" + ctor.CompileName, "", "", false, false, Type.Bool, null);
query.EnclosingClass = dt; // resolve here
members.Add(queryName, query);
ctor.QueryField = query;
@@ -937,7 +937,7 @@ namespace Microsoft.Dafny { Error(t.tok, "sorry, cannot instantiate type parameter with a subrange type");
}
}
- TypeParameter tp = allTypeParameters.Find(t.Name);
+ TypeParameter tp = t.ModuleName == null ? allTypeParameters.Find(t.Name) : null;
if (tp != null) {
if (t.TypeArgs.Count == 0) {
t.ResolvedParam = tp;
@@ -945,11 +945,32 @@ namespace Microsoft.Dafny { Error(t.tok, "Type parameter expects no type arguments: {0}", t.Name);
}
} else if (t.ResolvedClass == null) { // this test is because 'array' is already resolved; TODO: an alternative would be to pre-populate 'classes' with built-in references types like 'array' (and perhaps in the future 'string')
- TopLevelDecl d;
- if (!classes.TryGetValue(t.Name, out d)) {
+ TopLevelDecl d = null;
+ if (t.ModuleName != null) {
+ foreach (var imp in currentClass.Module.Imports) {
+ if (imp.Name == t.ModuleName.val) {
+ // now search among the types declared in module "imp"
+ foreach (var tld in imp.TopLevelDecls) { // this search is slow, but oh well
+ if (tld.Name == t.Name) {
+ // found the class
+ d = tld;
+ goto DONE_WITH_QUALIFIED_NAME;
+ }
+ }
+ Error(t.tok, "Undeclared class name {0} in module {1}", t.Name, t.ModuleName.val);
+ goto DONE_WITH_QUALIFIED_NAME;
+ }
+ }
+ Error(t.ModuleName, "Undeclared module name: {0} (did you forget a module import?)", t.ModuleName.val);
+ DONE_WITH_QUALIFIED_NAME: ;
+ } else if (!classes.TryGetValue(t.Name, out d)) {
Error(t.tok, "Undeclared top-level type or type parameter: {0} (did you forget a module import?)", t.Name);
+ }
+
+ if (d == null) {
+ // error has been reported above
} else if (d is AmbiguousTopLevelDecl) {
- Error(t.tok, "The name {0} ambiguously refers to a type in one of the modules {1}", t.Name, ((AmbiguousTopLevelDecl)d).ModuleNames());
+ Error(t.tok, "The name {0} ambiguously refers to a type in one of the modules {1} (try qualifying the type name with the module name)", t.Name, ((AmbiguousTopLevelDecl)d).ModuleNames());
} else if (d is ArbitraryTypeDecl) {
t.ResolvedParam = ((ArbitraryTypeDecl)d).TheType; // resolve like a type parameter
} else {
@@ -973,7 +994,7 @@ namespace Microsoft.Dafny { Contract.Assert(d.TypeArgs.Count <= defaultTypeArguments.Count);
// automatically supply a prefix of the arguments from defaultTypeArguments
for (int i = 0; i < d.TypeArgs.Count; i++) {
- var typeArg = new UserDefinedType(t.tok, defaultTypeArguments[i].Name, new List<Type>());
+ var typeArg = new UserDefinedType(t.tok, defaultTypeArguments[i].Name, new List<Type>(), null);
typeArg.ResolvedParam = defaultTypeArguments[i]; // resolve "typeArg" here
t.TypeArgs.Add(typeArg);
}
@@ -1355,7 +1376,7 @@ namespace Microsoft.Dafny { Statement target = loopStack[loopStack.Count - s.BreakCount];
if (target.Labels == null) {
// make sure there is a label, because the compiler and translator will want to see a unique ID
- target.Labels = new LabelNode(target.Tok, null, null);
+ target.Labels = new LList<Label>(new Label(target.Tok, null), null);
}
s.TargetStmt = target;
if (specContextOnly && !target.IsGhost && !inSpecOnlyContext[target]) {
@@ -1818,13 +1839,15 @@ namespace Microsoft.Dafny { Contract.Assert(false); throw new cce.UnreachableException();
}
}
-
private void ResolveUpdateStmt(ConcreteUpdateStatement s, bool specContextOnly, Method method)
{
int prevErrorCount = ErrorCount;
// First, resolve all LHS's and expression-looking RHS's.
SeqSelectExpr arrayRangeLhs = null;
+ var update = s as UpdateStmt;
+
foreach (var lhs in s.Lhss) {
+ var ec = ErrorCount;
if (lhs is SeqSelectExpr) {
var sse = (SeqSelectExpr)lhs;
ResolveSeqSelectExpr(sse, true, true);
@@ -1834,14 +1857,34 @@ namespace Microsoft.Dafny { } else {
ResolveExpression(lhs, true);
}
+ if (update == null && ec == ErrorCount && specContextOnly && !AssignStmt.LhsIsToGhost(lhs)) {
+ Error(lhs, "cannot assign to non-ghost variable in a ghost context");
+ }
}
IToken firstEffectfulRhs = null;
CallRhs callRhs = null;
- var update = s as UpdateStmt;
// Resolve RHSs
if (update == null) {
var suchThat = (AssignSuchThatStmt)s; // this is the other possible subclass
- s.ResolvedStatements.Add(suchThat.Assume);
+ ResolveExpression(suchThat.Expr, true);
+ if (suchThat.AssumeToken == null) {
+ // to ease in the verification, only allow local variables as LHSs
+ var lhsNames = new Dictionary<string, object>();
+ foreach (var lhs in s.Lhss) {
+ if (!(lhs.Resolved is IdentifierExpr)) {
+ Error(lhs, "the assign-such-that statement currently only supports local-variable LHSs");
+ }
+ else {
+ var ie = (IdentifierExpr)lhs.Resolved;
+ if (lhsNames.ContainsKey(ie.Name)) {
+ // disallow same LHS.
+ Error(s, "duplicate variable in left-hand side of assign-such-that statement: {0}", ie.Name);
+ } else {
+ lhsNames.Add(ie.Name, null);
+ }
+ }
+ }
+ }
} else {
foreach (var rhs in update.Rhss) {
bool isEffectful;
@@ -1877,13 +1920,14 @@ namespace Microsoft.Dafny { var ie = lhs.Resolved as IdentifierExpr;
if (ie != null) {
if (lhsNameSet.ContainsKey(ie.Name)) {
- Error(s, "Duplicate variable in left-hand side of {1} statement: {0}", ie.Name, callRhs != null ? "call" : "assignment");
+ if (callRhs != null)
+ // only allow same LHS in a multiassignment, not a call statement
+ Error(s, "duplicate variable in left-hand side of call statement: {0}", ie.Name);
} else {
lhsNameSet.Add(ie.Name, null);
}
}
}
-
if (update != null) {
// figure out what kind of UpdateStmt this is
if (firstEffectfulRhs == null) {
@@ -2158,17 +2202,18 @@ namespace Microsoft.Dafny { foreach (Statement ss in blockStmt.Body) {
labeledStatements.PushMarker();
// push labels
- for (var lnode = ss.Labels; lnode != null; lnode = lnode.Next) {
- Contract.Assert(lnode.Label != null); // LabelNode's with .Label==null are added only during resolution of the break statements with 'stmt' as their target, which hasn't happened yet
- var prev = labeledStatements.Find(lnode.Label);
+ for (var l = ss.Labels; l != null; l = l.Next) {
+ var lnode = l.Data;
+ Contract.Assert(lnode.Name != null); // LabelNode's with .Label==null are added only during resolution of the break statements with 'stmt' as their target, which hasn't happened yet
+ var prev = labeledStatements.Find(lnode.Name);
if (prev == ss) {
Error(lnode.Tok, "duplicate label");
} else if (prev != null) {
Error(lnode.Tok, "label shadows an enclosing label");
} else {
- bool b = labeledStatements.Push(lnode.Label, ss);
+ bool b = labeledStatements.Push(lnode.Name, ss);
Contract.Assert(b); // since we just checked for duplicates, we expect the Push to succeed
- if (lnode == ss.Labels) { // add it only once
+ if (l == ss.Labels) { // add it only once
inSpecOnlyContext.Add(ss, specContextOnly);
}
}
@@ -2338,7 +2383,7 @@ namespace Microsoft.Dafny { }
if (!callsConstructor && rr.EType is UserDefinedType) {
var udt = (UserDefinedType)rr.EType;
- var cl = (ClassDecl)udt.ResolvedClass; // cast is guarantted by the call to rr.EType.IsRefType above, together with the "rr.EType is UserDefinedType" test
+ var cl = (ClassDecl)udt.ResolvedClass; // cast is guaranteed by the call to rr.EType.IsRefType above, together with the "rr.EType is UserDefinedType" test
if (cl.HasConstructor) {
Error(stmt, "when allocating an object of type '{0}', one of its constructor methods must be called", cl.Name);
}
@@ -2594,7 +2639,7 @@ namespace Microsoft.Dafny { dtv.InferredTypeArgs.Add(t);
subst.Add(dt.TypeArgs[i], t);
}
- expr.Type = new UserDefinedType(dtv.tok, dtv.DatatypeName, gt);
+ expr.Type = new UserDefinedType(dtv.tok, dtv.DatatypeName, gt, null);
ResolveType(expr.tok, expr.Type, null, true);
DatatypeCtor ctor;
@@ -2855,8 +2900,10 @@ namespace Microsoft.Dafny { case BinaryExpr.Opcode.Eq:
case BinaryExpr.Opcode.Neq:
- if (!UnifyTypes(e.E0.Type, e.E1.Type)) {
- Error(expr, "arguments must have the same type (got {0} and {1})", e.E0.Type, e.E1.Type);
+ if (!CouldPossiblyBeSameType(e.E0.Type, e.E1.Type)) {
+ if (!UnifyTypes(e.E0.Type, e.E1.Type)) {
+ Error(expr, "arguments must have the same type (got {0} and {1})", e.E0.Type, e.E1.Type);
+ }
}
expr.Type = Type.Bool;
break;
@@ -3248,6 +3295,35 @@ namespace Microsoft.Dafny { }
}
+ private bool CouldPossiblyBeSameType(Type A, Type B) {
+ if (A.IsTypeParameter || B.IsTypeParameter) {
+ return true;
+ }
+ if (A.IsArrayType && B.IsArrayType) {
+ Type a = UserDefinedType.ArrayElementType(A);
+ Type b = UserDefinedType.ArrayElementType(B);
+ return CouldPossiblyBeSameType(a, b);
+ }
+ if (A is UserDefinedType && B is UserDefinedType) {
+ UserDefinedType a = (UserDefinedType)A;
+ UserDefinedType b = (UserDefinedType)B;
+ if (a.ResolvedClass != null && b.ResolvedClass != null && a.ResolvedClass == b.ResolvedClass) {
+ if (a.TypeArgs.Count != b.TypeArgs.Count) {
+ return false; // this probably doesn't happen if the classes are the same.
+ }
+ for (int i = 0; i < a.TypeArgs.Count; i++) {
+ if (!CouldPossiblyBeSameType(a.TypeArgs[i], b.TypeArgs[i]))
+ return false;
+ }
+ // all parameters could be the same
+ return true;
+ }
+ // either we don't know what class it is yet, or the classes mismatch
+ return false;
+ }
+ return false;
+ }
+
/// <summary>
/// Generate an error for every non-ghost feature used in "expr".
/// Requires "expr" to have been successfully resolved.
diff --git a/Source/Dafny/Scanner.cs b/Source/Dafny/Scanner.cs index 0c91c68c..d35fc22f 100644 --- a/Source/Dafny/Scanner.cs +++ b/Source/Dafny/Scanner.cs @@ -211,8 +211,8 @@ public class UTF8Buffer: Buffer { public class Scanner {
const char EOL = '\n';
const int eofSym = 0; /* pdt */
- const int maxT = 108;
- const int noSym = 108;
+ const int maxT = 107;
+ const int noSym = 107;
[ContractInvariantMethod]
@@ -494,34 +494,34 @@ public class Scanner { 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;
- case "codatatype": t.kind = 16; break;
- case "var": t.kind = 20; break;
- case "type": t.kind = 22; break;
- case "method": t.kind = 25; break;
- case "constructor": t.kind = 26; break;
- case "returns": t.kind = 27; break;
- case "modifies": t.kind = 29; break;
- case "free": t.kind = 30; break;
- case "requires": t.kind = 31; break;
- case "ensures": t.kind = 32; break;
- case "decreases": t.kind = 33; break;
- case "bool": t.kind = 36; break;
- case "nat": t.kind = 37; break;
- case "int": t.kind = 38; break;
- case "set": t.kind = 39; break;
- case "multiset": t.kind = 40; break;
- case "seq": t.kind = 41; break;
- case "map": t.kind = 42; break;
- case "object": t.kind = 43; break;
+ case "datatype": t.kind = 14; break;
+ case "codatatype": t.kind = 15; break;
+ case "var": t.kind = 19; break;
+ case "type": t.kind = 21; break;
+ case "method": t.kind = 24; break;
+ case "constructor": t.kind = 25; break;
+ case "returns": t.kind = 26; break;
+ case "modifies": t.kind = 28; break;
+ case "free": t.kind = 29; break;
+ case "requires": t.kind = 30; break;
+ case "ensures": t.kind = 31; break;
+ case "decreases": t.kind = 32; break;
+ case "bool": t.kind = 35; break;
+ case "nat": t.kind = 36; break;
+ case "int": t.kind = 37; break;
+ case "set": t.kind = 38; break;
+ case "multiset": t.kind = 39; break;
+ case "seq": t.kind = 40; break;
+ case "map": t.kind = 41; break;
+ case "object": t.kind = 42; break;
case "function": t.kind = 44; break;
case "predicate": t.kind = 45; break;
case "reads": t.kind = 46; break;
case "label": t.kind = 49; break;
case "break": t.kind = 50; break;
case "return": t.kind = 51; break;
- case "new": t.kind = 54; break;
+ case "assume": t.kind = 54; break;
+ case "new": t.kind = 55; break;
case "choose": t.kind = 58; break;
case "if": t.kind = 59; break;
case "else": t.kind = 60; break;
@@ -530,20 +530,19 @@ public class Scanner { case "invariant": t.kind = 64; break;
case "match": t.kind = 65; break;
case "assert": t.kind = 66; break;
- case "assume": t.kind = 67; break;
- case "print": t.kind = 68; break;
- case "parallel": t.kind = 69; break;
- case "in": t.kind = 83; break;
- case "false": t.kind = 93; break;
- case "true": t.kind = 94; break;
- case "null": t.kind = 95; break;
- case "this": t.kind = 96; break;
- case "fresh": t.kind = 97; break;
- case "allocated": t.kind = 98; break;
- case "old": t.kind = 99; break;
- case "then": t.kind = 100; break;
- case "forall": t.kind = 102; break;
- case "exists": t.kind = 104; break;
+ case "print": t.kind = 67; break;
+ case "parallel": t.kind = 68; break;
+ case "in": t.kind = 82; break;
+ case "false": t.kind = 92; break;
+ case "true": t.kind = 93; break;
+ case "null": t.kind = 94; break;
+ case "this": t.kind = 95; break;
+ case "fresh": t.kind = 96; break;
+ case "allocated": t.kind = 97; break;
+ case "old": t.kind = 98; break;
+ case "then": t.kind = 99; break;
+ case "forall": t.kind = 101; break;
+ case "exists": t.kind = 103; break;
default: break;
}
}
@@ -649,15 +648,15 @@ public class Scanner { else if (ch >= '0' && ch <= '9') {AddCh(); goto case 18;}
else {t.kind = 3; break;}
case 19:
- {t.kind = 19; break;}
+ {t.kind = 18; break;}
case 20:
- {t.kind = 21; break;}
+ {t.kind = 20; break;}
case 21:
- {t.kind = 28; break;}
+ {t.kind = 27; break;}
case 22:
- {t.kind = 34; break;}
+ {t.kind = 33; break;}
case 23:
- {t.kind = 35; break;}
+ {t.kind = 34; break;}
case 24:
{t.kind = 47; break;}
case 25:
@@ -667,63 +666,63 @@ public class Scanner { case 27:
{t.kind = 53; break;}
case 28:
- {t.kind = 55; break;}
- case 29:
{t.kind = 56; break;}
+ case 29:
+ {t.kind = 57; break;}
case 30:
{t.kind = 62; break;}
case 31:
if (ch == '>') {AddCh(); goto case 32;}
else {goto case 0;}
case 32:
- {t.kind = 70; break;}
+ {t.kind = 69; break;}
case 33:
- {t.kind = 71; break;}
+ {t.kind = 70; break;}
case 34:
- {t.kind = 72; break;}
+ {t.kind = 71; break;}
case 35:
- {t.kind = 73; break;}
+ {t.kind = 72; break;}
case 36:
if (ch == '&') {AddCh(); goto case 37;}
else {goto case 0;}
case 37:
- {t.kind = 74; break;}
+ {t.kind = 73; break;}
case 38:
- {t.kind = 75; break;}
+ {t.kind = 74; break;}
case 39:
- {t.kind = 76; break;}
+ {t.kind = 75; break;}
case 40:
- {t.kind = 77; break;}
+ {t.kind = 76; break;}
case 41:
- {t.kind = 80; break;}
+ {t.kind = 79; break;}
case 42:
- {t.kind = 81; break;}
+ {t.kind = 80; break;}
case 43:
- {t.kind = 82; break;}
+ {t.kind = 81; break;}
case 44:
- {t.kind = 85; break;}
+ {t.kind = 84; break;}
case 45:
- {t.kind = 86; break;}
+ {t.kind = 85; break;}
case 46:
- {t.kind = 87; break;}
+ {t.kind = 86; break;}
case 47:
- {t.kind = 88; break;}
+ {t.kind = 87; break;}
case 48:
- {t.kind = 89; break;}
+ {t.kind = 88; break;}
case 49:
- {t.kind = 90; break;}
+ {t.kind = 89; break;}
case 50:
- {t.kind = 91; break;}
+ {t.kind = 90; break;}
case 51:
- {t.kind = 92; break;}
+ {t.kind = 91; break;}
case 52:
- {t.kind = 103; break;}
+ {t.kind = 102; break;}
case 53:
- {t.kind = 105; break;}
+ {t.kind = 104; break;}
case 54:
- {t.kind = 106; break;}
+ {t.kind = 105; break;}
case 55:
- {t.kind = 107; break;}
+ {t.kind = 106; break;}
case 56:
recEnd = pos; recKind = 5;
if (ch == '=') {AddCh(); goto case 26;}
@@ -731,43 +730,43 @@ public class Scanner { else if (ch == ':') {AddCh(); goto case 54;}
else {t.kind = 5; break;}
case 57:
- recEnd = pos; recKind = 17;
+ recEnd = pos; recKind = 16;
if (ch == '>') {AddCh(); goto case 30;}
else if (ch == '=') {AddCh(); goto case 63;}
- else {t.kind = 17; break;}
+ else {t.kind = 16; break;}
case 58:
- recEnd = pos; recKind = 18;
+ recEnd = pos; recKind = 17;
if (ch == '|') {AddCh(); goto case 39;}
- else {t.kind = 18; break;}
+ else {t.kind = 17; break;}
case 59:
- recEnd = pos; recKind = 23;
+ recEnd = pos; recKind = 22;
if (ch == '=') {AddCh(); goto case 64;}
- else {t.kind = 23; break;}
+ else {t.kind = 22; break;}
case 60:
- recEnd = pos; recKind = 24;
+ recEnd = pos; recKind = 23;
if (ch == '=') {AddCh(); goto case 41;}
- else {t.kind = 24; break;}
+ else {t.kind = 23; break;}
case 61:
- recEnd = pos; recKind = 57;
+ recEnd = pos; recKind = 43;
if (ch == '.') {AddCh(); goto case 65;}
- else {t.kind = 57; break;}
+ else {t.kind = 43; break;}
case 62:
- recEnd = pos; recKind = 84;
+ recEnd = pos; recKind = 83;
if (ch == '=') {AddCh(); goto case 42;}
else if (ch == '!') {AddCh(); goto case 43;}
- else {t.kind = 84; break;}
+ else {t.kind = 83; break;}
case 63:
- recEnd = pos; recKind = 78;
+ recEnd = pos; recKind = 77;
if (ch == '>') {AddCh(); goto case 34;}
- else {t.kind = 78; break;}
+ else {t.kind = 77; break;}
case 64:
- recEnd = pos; recKind = 79;
+ recEnd = pos; recKind = 78;
if (ch == '=') {AddCh(); goto case 31;}
- else {t.kind = 79; break;}
+ else {t.kind = 78; break;}
case 65:
- recEnd = pos; recKind = 101;
+ recEnd = pos; recKind = 100;
if (ch == '.') {AddCh(); goto case 21;}
- else {t.kind = 101; break;}
+ else {t.kind = 100; break;}
}
t.val = new String(tval, 0, tlen);
diff --git a/Source/Dafny/Translator.cs b/Source/Dafny/Translator.cs index 0189c11b..c05d9a38 100644 --- a/Source/Dafny/Translator.cs +++ b/Source/Dafny/Translator.cs @@ -574,7 +574,7 @@ namespace Microsoft.Dafny { } else if (member is Function) {
Function f = (Function)member;
AddFunction(f);
- if (f.IsRecursive && !f.IsUnlimited) {
+ if (f.IsRecursive) {
AddLimitedAxioms(f, 2);
AddLimitedAxioms(f, 1);
}
@@ -586,7 +586,7 @@ namespace Microsoft.Dafny { } else {
AddFunctionAxiom(f, body, f.Ens, null, layerOffset);
}
- if (!f.IsRecursive || f.IsUnlimited) { break; }
+ if (!f.IsRecursive) { break; }
}
AddFrameAxiom(f);
AddWellformednessCheck(f);
@@ -666,7 +666,7 @@ namespace Microsoft.Dafny { // create and resolve datatype value
var r = new DatatypeValue(mc.tok, mc.Ctor.EnclosingDatatype.Name, mc.Ctor.Name, rArgs);
r.Ctor = mc.Ctor;
- r.Type = new UserDefinedType(mc.tok, mc.Ctor.EnclosingDatatype.Name, new List<Type>()/*this is not right, but it seems like it won't matter here*/);
+ r.Type = new UserDefinedType(mc.tok, mc.Ctor.EnclosingDatatype.Name, new List<Type>()/*this is not right, but it seems like it won't matter here*/, null);
Dictionary<IVariable, Expression> substMap = new Dictionary<IVariable, Expression>();
substMap.Add(formal, r);
@@ -716,7 +716,7 @@ namespace Microsoft.Dafny { Bpl.Axiom/*!*/ FunctionAxiom(Function/*!*/ f, FunctionAxiomVisibility visibility, Expression body, List<Expression/*!*/>/*!*/ ens, Specialization specialization, int layerOffset) {
Contract.Requires(f != null);
Contract.Requires(ens != null);
- Contract.Requires(layerOffset == 0 || (layerOffset == 1 && f.IsRecursive && !f.IsUnlimited));
+ Contract.Requires(layerOffset == 0 || (layerOffset == 1 && f.IsRecursive));
Contract.Requires(predef != null);
Contract.Requires(f.EnclosingClass != null);
@@ -895,7 +895,7 @@ namespace Microsoft.Dafny { void AddLimitedAxioms(Function f, int fromLayer) {
Contract.Requires(f != null);
- Contract.Requires(f.IsRecursive && !f.IsUnlimited);
+ Contract.Requires(f.IsRecursive);
Contract.Requires(fromLayer == 1 || fromLayer == 2);
Contract.Requires(sink != null && predef != null);
// With fromLayer==1, generate:
@@ -1380,7 +1380,7 @@ namespace Microsoft.Dafny { /// F(h0,formals) == F(h1,formals)
/// );
///
- /// If the function is a recursive, non-unlimited function, then the same axiom is also produced for "F#limited" instead of "F".
+ /// If the function is a recursive function, then the same axiom is also produced for "F#limited" instead of "F".
/// </summary>
void AddFrameAxiom(Function f)
{
@@ -1459,7 +1459,7 @@ namespace Microsoft.Dafny { Bpl.Expr.Imp(Bpl.Expr.And(wellFormed, heapSucc),
Bpl.Expr.Imp(q0, eq)));
sink.TopLevelDeclarations.Add(new Bpl.Axiom(f.tok, ax, axiomComment));
- if (axiomComment != null && f.IsRecursive && !f.IsUnlimited) {
+ if (axiomComment != null && f.IsRecursive) {
fn = new Bpl.FunctionCall(new Bpl.IdentifierExpr(f.tok, FunctionName(f, 0), TrType(f.ResultType)));
axiomComment = null; // the comment goes only with the first frame axiom
} else {
@@ -2933,7 +2933,7 @@ namespace Microsoft.Dafny { Bpl.Function func = new Bpl.Function(f.tok, f.FullName, typeParams, args, res);
sink.TopLevelDeclarations.Add(func);
- if (f.IsRecursive && !f.IsUnlimited) {
+ if (f.IsRecursive) {
sink.TopLevelDeclarations.Add(new Bpl.Function(f.tok, FunctionName(f, 0), args, res));
sink.TopLevelDeclarations.Add(new Bpl.Function(f.tok, FunctionName(f, 2), args, res));
}
@@ -3403,7 +3403,7 @@ namespace Microsoft.Dafny { } else if (stmt is BreakStmt) {
AddComment(builder, stmt, "break statement");
var s = (BreakStmt)stmt;
- builder.Add(new GotoCmd(s.Tok, new StringSeq("after_" + s.TargetStmt.Labels.UniqueId)));
+ builder.Add(new GotoCmd(s.Tok, new StringSeq("after_" + s.TargetStmt.Labels.Data.UniqueId)));
} else if (stmt is ReturnStmt) {
var s = (ReturnStmt)stmt;
AddComment(builder, stmt, "return statement");
@@ -3414,7 +3414,11 @@ namespace Microsoft.Dafny { } else if (stmt is AssignSuchThatStmt) {
var s = (AssignSuchThatStmt)stmt;
AddComment(builder, s, "assign-such-that statement");
- // treat like a parallel havoc, followed by an assume
+ // Essentially, treat like an assert, a parallel havoc, and an assume. However, we also need to check
+ // the well-formedness of the expression, which is easiest to do after the havoc. So, we do the havoc
+ // first, then the well-formedness check, then the assert (unless the whole statement is an assume), and
+ // finally the assume.
+
// Here comes the havoc part
var lhss = new List<Expression>();
var havocRhss = new List<AssignmentRhs>();
@@ -3424,10 +3428,40 @@ namespace Microsoft.Dafny { }
List<AssignToLhs> lhsBuilder;
List<Bpl.IdentifierExpr> bLhss;
- ProcessLhss(lhss, false, builder, locals, etran, out lhsBuilder, out bLhss);
+ Bpl.Expr[] ignore1, ignore2;
+ string[] ignore3;
+ ProcessLhss(lhss, false, true, builder, locals, etran, out lhsBuilder, out bLhss, out ignore1, out ignore2, out ignore3);
ProcessRhss(lhsBuilder, bLhss, lhss, havocRhss, builder, locals, etran);
+ // Here comes the well-formedness check
+ TrStmt_CheckWellformed(s.Expr, builder, locals, etran, false);
+ // Here comes the assert part
+ if (s.AssumeToken == null) {
+ var substMap = new Dictionary<IVariable, Expression>();
+ var bvars = new List<BoundVar>();
+ foreach (var lhs in s.Lhss) {
+ var l = lhs.Resolved;
+ if (l is IdentifierExpr) {
+ var x = (IdentifierExpr)l;
+ BoundVar bv;
+ IdentifierExpr ie;
+ CloneVariableAsBoundVar(x.tok, x.Var, "$as#" + x.Name, out bv, out ie);
+ bvars.Add(bv);
+ substMap.Add(x.Var, ie);
+ } else {
+ // other forms of LHSs have been ruled out by the resolver (it would be possible to
+ // handle them, but it would involve heap-update expressions--the translation would take
+ // effort, and it's not certain that the existential would be successful in verification).
+ Contract.Assume(false); // unexpected case
+ }
+ }
+ var bvs = new VariableSeq();
+ var typeAntecedent = etran.TrBoundVariables(bvars, bvs);
+ var substE = etran.TrExpr(Substitute(s.Expr, null, substMap));
+ var ex = new Bpl.ExistsExpr(s.Tok, bvs, BplAnd(typeAntecedent, substE));
+ builder.Add(Assert(s.Tok, ex, "cannot establish the existence of LHS values that satisfy the such-that predicate"));
+ }
// End by doing the assume
- TrStmt(s.Assume, builder, locals, etran);
+ builder.Add(new Bpl.AssumeCmd(s.Tok, etran.TrExpr(s.Expr)));
builder.Add(CaptureState(s.Tok)); // just do one capture state--here, at the very end (that is, don't do one before the assume)
} else if (stmt is UpdateStmt) {
@@ -3443,11 +3477,28 @@ namespace Microsoft.Dafny { foreach (var lhs in s.Lhss) {
lhss.Add(lhs.Resolved);
}
- bool rhssCanAffectPreviouslyKnownExpressions = s.Rhss.Exists(rhs => rhs.CanAffectPreviouslyKnownExpressions);
List<AssignToLhs> lhsBuilder;
List<Bpl.IdentifierExpr> bLhss;
- ProcessLhss(lhss, rhssCanAffectPreviouslyKnownExpressions, builder, locals, etran, out lhsBuilder, out bLhss);
- ProcessRhss(lhsBuilder, bLhss, lhss, s.Rhss, builder, locals, etran);
+ // note: because we have more than one expression, we always must assign to Boogie locals in a two
+ // phase operation. Thus rhssCanAffectPreviouslyKnownExpressions is just true.
+ Contract.Assert(1 < lhss.Count);
+
+ Bpl.Expr[] lhsObjs, lhsFields;
+ string[] lhsNames;
+ ProcessLhss(lhss, true, false, builder, locals, etran, out lhsBuilder, out bLhss, out lhsObjs, out lhsFields, out lhsNames);
+ // We know that, because the translation saves to a local variable, that the RHS always need to
+ // generate a new local, i.e. bLhss is just all nulls.
+ Contract.Assert(Contract.ForAll(bLhss, lhs => lhs == null));
+ // This generates the assignments, and gives them to us as finalRhss.
+ var finalRhss = ProcessUpdateAssignRhss(lhss, s.Rhss, builder, locals, etran);
+ // ProcessLhss has laid down framing conditions and the ProcessUpdateAssignRhss will check subranges (nats),
+ // but we need to generate the distinctness condition (two LHS are equal only when the RHS is also
+ // equal). We need both the LHS and the RHS to do this, which is why we need to do it here.
+ CheckLhssDistinctness(finalRhss, lhss, builder, etran, lhsObjs, lhsFields, lhsNames);
+ // Now actually perform the assignments to the LHS.
+ for (int i = 0; i < lhss.Count; i++) {
+ lhsBuilder[i](finalRhss[i], builder, etran);
+ }
builder.Add(CaptureState(s.Tok));
}
@@ -3471,7 +3522,7 @@ namespace Microsoft.Dafny { foreach (Statement ss in ((BlockStmt)stmt).Body) {
TrStmt(ss, builder, locals, etran);
if (ss.Labels != null) {
- builder.AddLabelCmd("after_" + ss.Labels.UniqueId);
+ builder.AddLabelCmd("after_" + ss.Labels.Data.UniqueId);
}
}
} else if (stmt is IfStmt) {
@@ -4235,7 +4286,9 @@ namespace Microsoft.Dafny { void TrCallStmt(CallStmt s, Bpl.StmtListBuilder builder, Bpl.VariableSeq locals, ExpressionTranslator etran, Bpl.Expr actualReceiver) {
List<AssignToLhs> lhsBuilders;
List<Bpl.IdentifierExpr> bLhss;
- ProcessLhss(s.Lhs, true, builder, locals, etran, out lhsBuilders, out bLhss);
+ Bpl.Expr[] ignore1, ignore2;
+ string[] ignore3;
+ ProcessLhss(s.Lhs, true, true, builder, locals, etran, out lhsBuilders, out bLhss, out ignore1, out ignore2, out ignore3);
Contract.Assert(s.Lhs.Count == lhsBuilders.Count);
Contract.Assert(s.Lhs.Count == bLhss.Count);
var lhsTypes = new List<Type>();
@@ -4869,8 +4922,10 @@ namespace Microsoft.Dafny { List<AssignToLhs> lhsBuilder;
List<Bpl.IdentifierExpr> bLhss;
var lhss = new List<Expression>() { lhs };
- ProcessLhss(lhss, rhs.CanAffectPreviouslyKnownExpressions, builder, locals, etran,
- out lhsBuilder, out bLhss);
+ Bpl.Expr[] ignore1, ignore2;
+ string[] ignore3;
+ ProcessLhss(lhss, rhs.CanAffectPreviouslyKnownExpressions, true, builder, locals, etran,
+ out lhsBuilder, out bLhss, out ignore1, out ignore2, out ignore3);
Contract.Assert(lhsBuilder.Count == 1 && bLhss.Count == 1); // guaranteed by postcondition of ProcessLhss
var rhss = new List<AssignmentRhs>() { rhs };
@@ -4919,16 +4974,104 @@ namespace Microsoft.Dafny { }
}
+ List<Bpl.IdentifierExpr> ProcessUpdateAssignRhss(List<Expression> lhss, List<AssignmentRhs> rhss,
+ Bpl.StmtListBuilder builder, Bpl.VariableSeq locals, ExpressionTranslator etran) {
+ Contract.Requires(cce.NonNullElements(lhss));
+ Contract.Requires(cce.NonNullElements(rhss));
+ Contract.Requires(builder != null);
+ Contract.Requires(cce.NonNullElements(locals));
+ Contract.Requires(etran != null);
+ Contract.Requires(predef != null);
+ Contract.Ensures(Contract.ForAll(Contract.Result<List<Bpl.IdentifierExpr>>(), i => i != null));
+
+ var finalRhss = new List<Bpl.IdentifierExpr>();
+ for (int i = 0; i < lhss.Count; i++) {
+ var lhs = lhss[i];
+ // the following assumes are part of the precondition, really
+ Contract.Assume(!(lhs is ConcreteSyntaxExpression));
+ Contract.Assume(!(lhs is SeqSelectExpr && !((SeqSelectExpr)lhs).SelectOne)); // array-range assignments are not allowed
+
+ Type lhsType = null;
+ if (lhs is IdentifierExpr) {
+ lhsType = lhs.Type;
+ } else if (lhs is FieldSelectExpr) {
+ var fse = (FieldSelectExpr)lhs;
+ lhsType = fse.Field.Type;
+ }
+ var bRhs = TrAssignmentRhs(rhss[i].Tok, null, lhsType, rhss[i], lhs.Type, builder, locals, etran);
+ finalRhss.Add(bRhs);
+ }
+ return finalRhss;
+ }
+
+
+ private void CheckLhssDistinctness(List<Bpl.IdentifierExpr> rhs, List<Expression> lhss, StmtListBuilder builder, ExpressionTranslator etran,
+ Bpl.Expr[] objs, Bpl.Expr[] fields, string[] names) {
+ Contract.Requires(cce.NonNullElements(lhss));
+ Contract.Requires(builder != null);
+ Contract.Requires(etran != null);
+ Contract.Requires(predef != null);
+
+ for (int i = 0; i < lhss.Count; i++) {
+ var lhs = lhss[i];
+ Contract.Assume(!(lhs is ConcreteSyntaxExpression));
+ IToken tok = lhs.tok;
+
+ if (lhs is IdentifierExpr) {
+ for (int j = 0; j < i; j++) {
+ var prev = lhss[j] as IdentifierExpr;
+ if (prev != null && names[i] == names[j]) {
+ builder.Add(Assert(tok, Bpl.Expr.Imp(Bpl.Expr.True, Bpl.Expr.Eq(rhs[i],rhs[j])), string.Format("when left-hand sides {0} and {1} refer to the same location, they must have the same value", j, i)));
+ }
+ }
+ } else if (lhs is FieldSelectExpr) {
+ var fse = (FieldSelectExpr)lhs;
+ // check that this LHS is not the same as any previous LHSs
+ for (int j = 0; j < i; j++) {
+ var prev = lhss[j] as FieldSelectExpr;
+ if (prev != null && prev.Field == fse.Field) {
+ builder.Add(Assert(tok, Bpl.Expr.Imp(Bpl.Expr.Eq(objs[j], objs[i]), Bpl.Expr.Eq(rhs[i], rhs[j])), string.Format("when left-hand sides {0} and {1} refer to the same location, they must have the same value", j, i)));
+ }
+ }
+ } else if (lhs is SeqSelectExpr) {
+ SeqSelectExpr sel = (SeqSelectExpr)lhs;
+ // check that this LHS is not the same as any previous LHSs
+ for (int j = 0; j < i; j++) {
+ var prev = lhss[j] as SeqSelectExpr;
+ if (prev != null) {
+ builder.Add(Assert(tok,
+ Bpl.Expr.Imp(Bpl.Expr.And(Bpl.Expr.Eq(objs[j], objs[i]), Bpl.Expr.Eq(fields[j], fields[i])), Bpl.Expr.Eq(rhs[i], rhs[j])),
+ string.Format("when left-hand sides {0} and {1} may refer to the same location, they must have the same value", j, i)));
+ }
+ }
+ } else {
+ MultiSelectExpr mse = (MultiSelectExpr)lhs;
+ // check that this LHS is not the same as any previous LHSs
+ for (int j = 0; j < i; j++) {
+ var prev = lhss[j] as MultiSelectExpr;
+ if (prev != null) {
+ builder.Add(Assert(tok,
+ Bpl.Expr.Imp(Bpl.Expr.And(Bpl.Expr.Eq(objs[j], objs[i]), Bpl.Expr.Eq(fields[j], fields[i])), Bpl.Expr.Eq(rhs[i], rhs[j])),
+ string.Format("when left-hand sides {0} and {1} refer to the same location, they must have the same value", j, i)));
+ }
+ }
+
+ }
+ }
+ }
+
delegate void AssignToLhs(Bpl.Expr rhs, Bpl.StmtListBuilder builder, ExpressionTranslator etran);
/// <summary>
/// Creates a list of protected Boogie LHSs for the given Dafny LHSs. Along the way,
- /// builds code that checks that the LHSs are well-defined, denote different locations,
+ /// builds code that checks that the LHSs are well-defined,
/// and are allowed by the enclosing modifies clause.
+ /// Checks that they denote different locations iff checkDistinctness is true.
/// </summary>
- void ProcessLhss(List<Expression> lhss, bool rhsCanAffectPreviouslyKnownExpressions,
+ void ProcessLhss(List<Expression> lhss, bool rhsCanAffectPreviouslyKnownExpressions, bool checkDistinctness,
Bpl.StmtListBuilder builder, Bpl.VariableSeq locals, ExpressionTranslator etran,
- out List<AssignToLhs> lhsBuilders, out List<Bpl.IdentifierExpr/*may be null*/> bLhss) {
+ out List<AssignToLhs> lhsBuilders, out List<Bpl.IdentifierExpr/*may be null*/> bLhss,
+ out Bpl.Expr[] prevObj, out Bpl.Expr[] prevIndex, out string[] prevNames) {
Contract.Requires(cce.NonNullElements(lhss));
Contract.Requires(builder != null);
@@ -4943,17 +5086,31 @@ namespace Microsoft.Dafny { // for each Dafny LHS, build a protected Boogie LHS for the eventual assignment
lhsBuilders = new List<AssignToLhs>();
bLhss = new List<Bpl.IdentifierExpr>();
- var prevObj = new Bpl.Expr[lhss.Count];
- var prevIndex = new Bpl.Expr[lhss.Count];
+ prevObj = new Bpl.Expr[lhss.Count];
+ prevIndex = new Bpl.Expr[lhss.Count];
+ prevNames = new string[lhss.Count];
int i = 0;
+
+ var lhsNameSet = new Dictionary<string, object>();
+
foreach (var lhs in lhss) {
Contract.Assume(!(lhs is ConcreteSyntaxExpression));
IToken tok = lhs.tok;
TrStmt_CheckWellformed(lhs, builder, locals, etran, true);
if (lhs is IdentifierExpr) {
+ var ie = (IdentifierExpr)lhs;
+ // Note, the resolver does not check for duplicate IdentifierExpr's in LHSs, so do it here.
+ if (checkDistinctness) {
+ for (int j = 0; j < i; j++) {
+ var prev = lhss[j] as IdentifierExpr;
+ if (prev != null && ie.Name == prev.Name) {
+ builder.Add(Assert(tok, Bpl.Expr.False, string.Format("left-hand sides {0} and {1} refer to the same location", j, i)));
+ }
+ }
+ }
+ prevNames[i] = ie.Name;
var bLhs = (Bpl.IdentifierExpr)etran.TrExpr(lhs); // TODO: is this cast always justified?
- // Note, the resolver checks for duplicate IdentifierExpr's in LHSs
bLhss.Add(rhsCanAffectPreviouslyKnownExpressions ? null : bLhs);
lhsBuilders.Add(delegate(Bpl.Expr rhs, Bpl.StmtListBuilder bldr, ExpressionTranslator et) {
builder.Add(Bpl.Cmd.SimpleAssign(tok, bLhs, rhs));
@@ -4968,11 +5125,13 @@ namespace Microsoft.Dafny { // check that the enclosing modifies clause allows this object to be written: assert $_Frame[obj]);
builder.Add(Assert(tok, Bpl.Expr.SelectTok(tok, etran.TheFrame(tok), obj, GetField(fse)), "assignment may update an object not in the enclosing context's modifies clause"));
- // check that this LHS is not the same as any previous LHSs
- for (int j = 0; j < i; j++) {
- var prev = lhss[j] as FieldSelectExpr;
- if (prev != null && prev.Field == fse.Field) {
- builder.Add(Assert(tok, Bpl.Expr.Neq(prevObj[j], obj), string.Format("left-hand sides {0} and {1} may refer to the same location", j, i)));
+ if (checkDistinctness) {
+ // check that this LHS is not the same as any previous LHSs
+ for (int j = 0; j < i; j++) {
+ var prev = lhss[j] as FieldSelectExpr;
+ if (prev != null && prev.Field == fse.Field) {
+ builder.Add(Assert(tok, Bpl.Expr.Neq(prevObj[j], obj), string.Format("left-hand sides {0} and {1} may refer to the same location", j, i)));
+ }
}
}
@@ -4999,16 +5158,17 @@ namespace Microsoft.Dafny { // check that the enclosing modifies clause allows this object to be written: assert $_Frame[obj,index]);
builder.Add(Assert(tok, Bpl.Expr.SelectTok(tok, etran.TheFrame(tok), obj, fieldName), "assignment may update an array element not in the enclosing context's modifies clause"));
- // check that this LHS is not the same as any previous LHSs
- for (int j = 0; j < i; j++) {
- var prev = lhss[j] as SeqSelectExpr;
- if (prev != null) {
- builder.Add(Assert(tok,
- Bpl.Expr.Or(Bpl.Expr.Neq(prevObj[j], obj), Bpl.Expr.Neq(prevIndex[j], fieldName)),
- string.Format("left-hand sides {0} and {1} may refer to the same location", j, i)));
+ if (checkDistinctness) {
+ // check that this LHS is not the same as any previous LHSs
+ for (int j = 0; j < i; j++) {
+ var prev = lhss[j] as SeqSelectExpr;
+ if (prev != null) {
+ builder.Add(Assert(tok,
+ Bpl.Expr.Or(Bpl.Expr.Neq(prevObj[j], obj), Bpl.Expr.Neq(prevIndex[j], fieldName)),
+ string.Format("left-hand sides {0} and {1} may refer to the same location", j, i)));
+ }
}
}
-
bLhss.Add(null);
lhsBuilders.Add(delegate(Bpl.Expr rhs, Bpl.StmtListBuilder bldr, ExpressionTranslator et) {
var h = (Bpl.IdentifierExpr)et.HeapExpr; // TODO: is this cast always justified?
@@ -5030,16 +5190,17 @@ namespace Microsoft.Dafny { prevIndex[i] = fieldName;
builder.Add(Assert(tok, Bpl.Expr.SelectTok(tok, etran.TheFrame(tok), obj, fieldName), "assignment may update an array element not in the enclosing context's modifies clause"));
- // check that this LHS is not the same as any previous LHSs
- for (int j = 0; j < i; j++) {
- var prev = lhss[j] as MultiSelectExpr;
- if (prev != null) {
- builder.Add(Assert(tok,
- Bpl.Expr.Or(Bpl.Expr.Neq(prevObj[j], obj), Bpl.Expr.Neq(prevIndex[j], fieldName)),
- string.Format("left-hand sides {0} and {1} may refer to the same location", j, i)));
+ if (checkDistinctness) {
+ // check that this LHS is not the same as any previous LHSs
+ for (int j = 0; j < i; j++) {
+ var prev = lhss[j] as MultiSelectExpr;
+ if (prev != null) {
+ builder.Add(Assert(tok,
+ Bpl.Expr.Or(Bpl.Expr.Neq(prevObj[j], obj), Bpl.Expr.Neq(prevIndex[j], fieldName)),
+ string.Format("left-hand sides {0} and {1} may refer to the same location", j, i)));
+ }
}
}
-
bLhss.Add(null);
lhsBuilders.Add(delegate(Bpl.Expr rhs, Bpl.StmtListBuilder bldr, ExpressionTranslator et) {
var h = (Bpl.IdentifierExpr)et.HeapExpr; // TODO: is this cast always justified?
@@ -5097,7 +5258,10 @@ namespace Microsoft.Dafny { } else if (rhs is HavocRhs) {
builder.Add(new Bpl.HavocCmd(tok, new Bpl.IdentifierExprSeq(bLhs)));
-
+ var isNat = CheckSubrange_Expr(tok, bLhs, checkSubrangeType);
+ if (isNat != null) {
+ builder.Add(new Bpl.AssumeCmd(tok, isNat));
+ }
} else {
Contract.Assert(rhs is TypeRhs); // otherwise, an unexpected AssignmentRhs
TypeRhs tRhs = (TypeRhs)rhs;
@@ -5535,12 +5699,12 @@ namespace Microsoft.Dafny { } else if (expr is FunctionCallExpr) {
FunctionCallExpr e = (FunctionCallExpr)expr;
- int offsetToUse = e.Function.IsRecursive && !e.Function.IsUnlimited ? this.layerOffset : 0;
- if (e.Function.IsRecursive && !e.Function.IsUnlimited) {
+ int offsetToUse = e.Function.IsRecursive ? this.layerOffset : 0;
+ if (e.Function.IsRecursive) {
Statistics_CustomLayerFunctionCount++;
}
string nm = FunctionName(e.Function, 1 + offsetToUse);
- if (this.applyLimited_CurrentFunction != null && e.Function.IsRecursive && !e.Function.IsUnlimited) {
+ if (this.applyLimited_CurrentFunction != null && e.Function.IsRecursive) {
ModuleDecl module = cce.NonNull(e.Function.EnclosingClass).Module;
if (module == cce.NonNull(applyLimited_CurrentFunction.EnclosingClass).Module) {
if (module.CallGraph.GetSCCRepresentative(e.Function) == module.CallGraph.GetSCCRepresentative(applyLimited_CurrentFunction)) {
diff --git a/Source/GPUVerify/ArrayControlFlowAnalyser.cs b/Source/GPUVerify/ArrayControlFlowAnalyser.cs index 20036abe..f1ce9f1e 100644 --- a/Source/GPUVerify/ArrayControlFlowAnalyser.cs +++ b/Source/GPUVerify/ArrayControlFlowAnalyser.cs @@ -99,7 +99,11 @@ namespace GPUVerify private void Analyse(Implementation Impl)
{
- Analyse(Impl, Impl.StructuredStmts);
+ if (CommandLineOptions.Unstructured)
+ foreach (var b in Impl.Blocks)
+ Analyse(Impl, b.Cmds);
+ else
+ Analyse(Impl, Impl.StructuredStmts);
}
private void Analyse(Implementation impl, StmtList stmtList)
@@ -110,9 +114,29 @@ namespace GPUVerify }
}
- private void Analyse(Implementation impl, BigBlock bb)
+ private void ExprMayAffectControlFlow(Implementation impl, Expr e)
{
- foreach (Cmd c in bb.simpleCmds)
+ var visitor = new VariablesOccurringInExpressionVisitor();
+ visitor.VisitExpr(e);
+ foreach (Variable v in visitor.GetVariables())
+ {
+ if (!mayBeDerivedFrom[impl.Name].ContainsKey(v.Name))
+ {
+ continue;
+ }
+ foreach (string s in mayBeDerivedFrom[impl.Name][v.Name])
+ {
+ if (!arraysWhichMayAffectControlFlow.Contains(s))
+ {
+ SetArrayMayAffectControlFlow(s);
+ }
+ }
+ }
+ }
+
+ private void Analyse(Implementation impl, CmdSeq cs)
+ {
+ foreach (var c in cs)
{
if (c is AssignCmd)
{
@@ -189,28 +213,23 @@ namespace GPUVerify }
}
+ else if (c is AssumeCmd)
+ {
+ var assumeCmd = c as AssumeCmd;
+ ExprMayAffectControlFlow(impl, assumeCmd.Expr);
+ }
}
+ }
+
+ private void Analyse(Implementation impl, BigBlock bb)
+ {
+ Analyse(impl, bb.simpleCmds);
if (bb.ec is WhileCmd)
{
WhileCmd wc = bb.ec as WhileCmd;
- VariablesOccurringInExpressionVisitor visitor = new VariablesOccurringInExpressionVisitor();
- visitor.VisitExpr(wc.Guard);
- foreach (Variable v in visitor.GetVariables())
- {
- if (!mayBeDerivedFrom[impl.Name].ContainsKey(v.Name))
- {
- continue;
- }
- foreach (string s in mayBeDerivedFrom[impl.Name][v.Name])
- {
- if (!arraysWhichMayAffectControlFlow.Contains(s))
- {
- SetArrayMayAffectControlFlow(s);
- }
- }
- }
+ ExprMayAffectControlFlow(impl, wc.Guard);
Analyse(impl, wc.Body);
}
@@ -218,22 +237,7 @@ namespace GPUVerify {
IfCmd ifCmd = bb.ec as IfCmd;
- VariablesOccurringInExpressionVisitor visitor = new VariablesOccurringInExpressionVisitor();
- visitor.VisitExpr(ifCmd.Guard);
- foreach (Variable v in visitor.GetVariables())
- {
- if (!mayBeDerivedFrom[impl.Name].ContainsKey(v.Name))
- {
- continue;
- }
- foreach (string s in mayBeDerivedFrom[impl.Name][v.Name])
- {
- if (!arraysWhichMayAffectControlFlow.Contains(s))
- {
- SetArrayMayAffectControlFlow(s);
- }
- }
- }
+ ExprMayAffectControlFlow(impl, ifCmd.Guard);
Analyse(impl, ifCmd.thn);
if (ifCmd.elseBlock != null)
diff --git a/Source/GPUVerify/BlockPredicator.cs b/Source/GPUVerify/BlockPredicator.cs index 6521960c..a006bde6 100644 --- a/Source/GPUVerify/BlockPredicator.cs +++ b/Source/GPUVerify/BlockPredicator.cs @@ -9,6 +9,7 @@ namespace GPUVerify { class BlockPredicator { + GPUVerifier verifier; Program prog; Implementation impl; Graph<Block> blockGraph; @@ -16,14 +17,15 @@ class BlockPredicator { Expr returnBlockId; LocalVariable curVar, pVar; - IdentifierExpr cur, p; + IdentifierExpr cur, p, fp; Expr pExpr; Dictionary<Microsoft.Boogie.Type, IdentifierExpr> havocVars = new Dictionary<Microsoft.Boogie.Type, IdentifierExpr>(); Dictionary<Block, Expr> blockIds = new Dictionary<Block, Expr>(); HashSet<Block> doneBlocks = new HashSet<Block>(); - BlockPredicator(Program p, Implementation i) { + BlockPredicator(GPUVerifier v, Program p, Implementation i) { + verifier = v; prog = p; impl = i; } @@ -145,7 +147,7 @@ class BlockPredicator { var newBlocks = new List<Block>(); - var fp = Expr.Ident(impl.InParams[0]); + fp = Expr.Ident(impl.InParams[0]); Block entryBlock = new Block(); entryBlock.Label = "entry"; entryBlock.Cmds = new CmdSeq(Cmd.SimpleAssign(Token.NoToken, cur, @@ -158,6 +160,16 @@ class BlockPredicator { var prevBlock = entryBlock; foreach (var n in sortedBlocks) { if (n.Item2) { + var backedgeBlock = new Block(); + newBlocks.Add(backedgeBlock); + + backedgeBlock.Label = n.Item1.Label + ".backedge"; + backedgeBlock.Cmds = new CmdSeq(new AssumeCmd(Token.NoToken, + Expr.Eq(cur, blockIds[n.Item1]), + new QKeyValue(Token.NoToken, "backedge", new List<object>(), null))); + backedgeBlock.TransferCmd = new GotoCmd(Token.NoToken, + new BlockSeq(n.Item1)); + var tailBlock = new Block(); newBlocks.Add(tailBlock); @@ -166,7 +178,7 @@ class BlockPredicator { Expr.Neq(cur, blockIds[n.Item1]))); prevBlock.TransferCmd = new GotoCmd(Token.NoToken, - new BlockSeq(tailBlock, n.Item1)); + new BlockSeq(backedgeBlock, tailBlock)); prevBlock = tailBlock; } else { var runBlock = n.Item1; @@ -174,6 +186,10 @@ class BlockPredicator { pExpr = Expr.Eq(cur, blockIds[runBlock]); CmdSeq newCmdSeq = new CmdSeq(); + if (CommandLineOptions.Inference && blockGraph.Headers.Contains(runBlock)) { + AddUniformCandidateInvariant(newCmdSeq, runBlock); + AddNonUniformCandidateInvariant(newCmdSeq, runBlock); + } newCmdSeq.Add(Cmd.SimpleAssign(Token.NoToken, p, pExpr)); foreach (Cmd cmd in runBlock.Cmds) PredicateCmd(newCmdSeq, cmd); @@ -191,12 +207,43 @@ class BlockPredicator { impl.Blocks = newBlocks; } - public static void Predicate(Program p) { - foreach (var decl in p.TopLevelDeclarations) { + private void AddUniformCandidateInvariant(CmdSeq cs, Block header) { + cs.Add(verifier.CreateCandidateInvariant(Expr.Eq(cur, + new NAryExpr(Token.NoToken, + new IfThenElse(Token.NoToken), + new ExprSeq(fp, blockIds[header], returnBlockId))), + "uniform loop")); + } + + private void AddNonUniformCandidateInvariant(CmdSeq cs, Block header) { + var loopNodes = new HashSet<Block>(); + foreach (var b in blockGraph.BackEdgeNodes(header)) + loopNodes.UnionWith(blockGraph.NaturalLoops(header, b)); + var exits = new HashSet<Expr>(); + foreach (var ln in loopNodes) { + if (ln.TransferCmd is GotoCmd) { + var gCmd = (GotoCmd) ln.TransferCmd; + foreach (var exit in gCmd.labelTargets.Cast<Block>() + .Where(b => !loopNodes.Contains(b))) + exits.Add(blockIds[exit]); + } + if (ln.TransferCmd is ReturnCmd) + exits.Add(returnBlockId); + } + var curIsHeaderOrExit = exits.Aggregate((Expr)Expr.Eq(cur, blockIds[header]), + (e, exit) => Expr.Or(e, Expr.Eq(cur, exit))); + cs.Add(verifier.CreateCandidateInvariant(new NAryExpr(Token.NoToken, + new IfThenElse(Token.NoToken), + new ExprSeq(fp, curIsHeaderOrExit, Expr.Eq(cur, returnBlockId))), + "non-uniform loop")); + } + + public static void Predicate(GPUVerifier v, Program p) { + foreach (var decl in p.TopLevelDeclarations.ToList()) { if (decl is DeclWithFormals && !(decl is Function)) { var dwf = (DeclWithFormals)decl; var fpVar = new Formal(Token.NoToken, - new TypedIdent(Token.NoToken, "fp", + new TypedIdent(Token.NoToken, "_P", Microsoft.Boogie.Type.Bool), /*incoming=*/true); dwf.InParams = new VariableSeq( @@ -205,7 +252,7 @@ class BlockPredicator { } var impl = decl as Implementation; if (impl != null) - new BlockPredicator(p, impl).PredicateImplementation(); + new BlockPredicator(v, p, impl).PredicateImplementation(); } } diff --git a/Source/GPUVerify/CommandLineOptions.cs b/Source/GPUVerify/CommandLineOptions.cs index 7e6324b2..966f98eb 100644 --- a/Source/GPUVerify/CommandLineOptions.cs +++ b/Source/GPUVerify/CommandLineOptions.cs @@ -42,6 +42,8 @@ namespace GPUVerify public static bool Unstructured = false;
+ public static bool InterGroupRaceChecking = false;
+
public static int Parse(string[] args)
{
for (int i = 0; i < args.Length; i++)
@@ -184,6 +186,11 @@ namespace GPUVerify Unstructured = true;
break;
+ case "-interGroupRaceChecking":
+ case "/interGroupRaceChecking":
+ InterGroupRaceChecking = true;
+ break;
+
default:
inputFiles.Add(args[i]);
break;
diff --git a/Source/GPUVerify/ElementEncodingRaceInstrumenter.cs b/Source/GPUVerify/ElementEncodingRaceInstrumenter.cs index 7b78f0f1..cb880767 100644 --- a/Source/GPUVerify/ElementEncodingRaceInstrumenter.cs +++ b/Source/GPUVerify/ElementEncodingRaceInstrumenter.cs @@ -65,6 +65,12 @@ namespace GPUVerify MakeAccessedIndex(v, new IdentifierExpr(Token.NoToken, VariableForThread(2, OffsetParameter)), 2, "READ")
));
}
+
+ if (verifier.NonLocalState.getGroupSharedVariables().Contains(v) && CommandLineOptions.InterGroupRaceChecking)
+ {
+ WriteReadGuard = Expr.And(WriteReadGuard, verifier.ThreadsInSameGroup());
+ }
+
WriteReadGuard = Expr.Not(WriteReadGuard);
simpleCmds.Add(new AssertCmd(Token.NoToken, WriteReadGuard));
}
@@ -87,6 +93,12 @@ namespace GPUVerify MakeAccessedIndex(v, new IdentifierExpr(Token.NoToken, VariableForThread(2, OffsetParameter)), 2, "WRITE")
));
}
+
+ if (verifier.NonLocalState.getGroupSharedVariables().Contains(v) && CommandLineOptions.InterGroupRaceChecking)
+ {
+ WriteWriteGuard = Expr.And(WriteWriteGuard, verifier.ThreadsInSameGroup());
+ }
+
WriteWriteGuard = Expr.Not(WriteWriteGuard);
simpleCmds.Add(new AssertCmd(Token.NoToken, WriteWriteGuard));
@@ -105,6 +117,12 @@ namespace GPUVerify MakeAccessedIndex(v, new IdentifierExpr(Token.NoToken, VariableForThread(2, OffsetParameter)), 2, "READ")
));
}
+
+ if (verifier.NonLocalState.getGroupSharedVariables().Contains(v) && CommandLineOptions.InterGroupRaceChecking)
+ {
+ ReadWriteGuard = Expr.And(ReadWriteGuard, verifier.ThreadsInSameGroup());
+ }
+
ReadWriteGuard = Expr.Not(ReadWriteGuard);
simpleCmds.Add(new AssertCmd(Token.NoToken, ReadWriteGuard));
@@ -156,14 +174,6 @@ namespace GPUVerify return new AssignCmd(lhs.tok, lhss, rhss);
}
- protected override void SetNoAccessOccurred(IToken tok, BigBlock bb, Variable v, string AccessType)
- {
- IdentifierExpr AccessOccurred1 = new IdentifierExpr(tok,
- new VariableDualiser(1, null, null).VisitVariable(GPUVerifier.MakeAccessHasOccurredVariable(v.Name, AccessType)));
-
- bb.simpleCmds.Add(new AssumeCmd(Token.NoToken, Expr.Not(AccessOccurred1)));
- }
-
private Expr MakeAccessedIndex(Variable v, Expr offsetExpr, int Thread, string AccessType)
{
Expr result = new IdentifierExpr(v.tok, new VariableDualiser(Thread, null, null).VisitVariable(v.Clone() as Variable));
@@ -195,16 +205,16 @@ namespace GPUVerify }
- protected override void AddAccessedOffsetIsThreadGlobalIdCandidateInvariant(WhileCmd wc, Variable v, string ReadOrWrite)
+ protected override void AddAccessedOffsetsAreConstantCandidateInvariant(IRegion region, Variable v, IEnumerable<Expr> offsets, string ReadOrWrite)
{
- Expr expr = AccessedOffsetIsThreadGlobalIdExpr(v, ReadOrWrite, 1);
- verifier.AddCandidateInvariant(wc, expr, "accessed offset is global id");
+ Expr expr = AccessedOffsetsAreConstantExpr(v, offsets, ReadOrWrite, 1);
+ verifier.AddCandidateInvariant(region, expr, "accessed offsets are constant");
}
- protected override void AddAccessedOffsetIsThreadLocalIdCandidateInvariant(WhileCmd wc, Variable v, string ReadOrWrite)
- {
- Expr expr = AccessedOffsetIsThreadLocalIdExpr(v, ReadOrWrite, 1);
- verifier.AddCandidateInvariant(wc, expr, "accessed offset is local id");
+ private Expr AccessedOffsetsAreConstantExpr(Variable v, IEnumerable<Expr> offsets, string ReadOrWrite, int Thread) {
+ return Expr.Imp(
+ new IdentifierExpr(Token.NoToken, new VariableDualiser(Thread, null, null).VisitVariable(GPUVerifier.MakeAccessHasOccurredVariable(v.Name, ReadOrWrite))),
+ offsets.Select(ofs => (Expr)Expr.Eq(new IdentifierExpr(Token.NoToken, new VariableDualiser(Thread, null, null).VisitVariable(GPUVerifier.MakeOffsetXVariable(v, ReadOrWrite))), ofs)).Aggregate(Expr.Or));
}
private Expr AccessedOffsetIsThreadLocalIdExpr(Variable v, string ReadOrWrite, int Thread)
@@ -240,65 +250,10 @@ namespace GPUVerify return new VariableDualiser(Thread, null, null).VisitExpr(verifier.GlobalIdExpr(dimension).Clone() as Expr);
}
- private Expr GlobalSizeExpr(string dimension)
- {
- return GPUVerifier.MakeBitVectorBinaryBitVector("BV32_MUL",
- new IdentifierExpr(Token.NoToken, verifier.GetNumGroups(dimension)),
- new IdentifierExpr(Token.NoToken, verifier.GetGroupSize(dimension)));
- }
-
- protected override void AddAccessedOffsetIsThreadFlattened2DLocalIdCandidateInvariant(WhileCmd wc, Variable v, string ReadOrWrite)
- {
- Expr expr = AccessedOffsetIsThreadFlattened2DLocalIdExpr(v, ReadOrWrite, 1);
- verifier.AddCandidateInvariant(wc, expr, "accessed offset is flattened 2D local id");
- }
-
- private Expr AccessedOffsetIsThreadFlattened2DLocalIdExpr(Variable v, string ReadOrWrite, int Thread)
- {
- Expr expr = null;
- if (GPUVerifier.HasXDimension(v) && GPUVerifier.IndexTypeOfXDimension(v).Equals(verifier.GetTypeOfIdX()))
- {
- expr = Expr.Imp(
- AccessHasOccurred(v, ReadOrWrite, Thread),
- Expr.Eq(
- new IdentifierExpr(v.tok, new VariableDualiser(Thread, null, null).VisitVariable(GPUVerifier.MakeOffsetXVariable(v, ReadOrWrite))),
- GPUVerifier.MakeBitVectorBinaryBitVector("BV32_ADD", GPUVerifier.MakeBitVectorBinaryBitVector("BV32_MUL",
- new IdentifierExpr(v.tok, verifier.MakeThreadId(v.tok, "Y", Thread)), new IdentifierExpr(v.tok, verifier.GetGroupSize("X"))),
- new IdentifierExpr(v.tok, verifier.MakeThreadId(v.tok, "X", Thread)))
- )
- );
- }
- return expr;
- }
-
- protected override void AddAccessedOffsetIsThreadFlattened2DGlobalIdCandidateInvariant(WhileCmd wc, Variable v, string ReadOrWrite)
- {
- Expr expr = AccessedOffsetIsThreadFlattened2DGlobalIdExpr(v, ReadOrWrite, 1);
- verifier.AddCandidateInvariant(wc, expr, "accessed offset is flattened 2D global id");
- }
-
- private Expr AccessedOffsetIsThreadFlattened2DGlobalIdExpr(Variable v, string ReadOrWrite, int Thread)
- {
- Expr expr = null;
- if (GPUVerifier.HasXDimension(v) && GPUVerifier.IndexTypeOfXDimension(v).Equals(verifier.GetTypeOfIdX()))
- {
- expr = Expr.Imp(
- AccessHasOccurred(v, ReadOrWrite, Thread),
- Expr.Eq(
- new IdentifierExpr(v.tok, new VariableDualiser(Thread, null, null).VisitVariable(GPUVerifier.MakeOffsetXVariable(v, ReadOrWrite))),
- GPUVerifier.MakeBitVectorBinaryBitVector("BV32_ADD", GPUVerifier.MakeBitVectorBinaryBitVector("BV32_MUL",
- GlobalIdExpr("Y", Thread), GlobalSizeExpr("X")),
- GlobalIdExpr("X", Thread))
- )
- );
- }
- return expr;
- }
-
- protected override void AddAccessedOffsetInRangeCTimesLocalIdToCTimesLocalIdPlusC(WhileCmd wc, Variable v, Expr constant, string ReadOrWrite)
+ protected override void AddAccessedOffsetInRangeCTimesLocalIdToCTimesLocalIdPlusC(IRegion region, Variable v, Expr constant, string ReadOrWrite)
{
Expr expr = MakeCTimesLocalIdRangeExpression(v, constant, ReadOrWrite, 1);
- verifier.AddCandidateInvariant(wc,
+ verifier.AddCandidateInvariant(region,
expr, "accessed offset in range [ C*local_id, (C+1)*local_id )");
}
@@ -329,10 +284,10 @@ namespace GPUVerify return new IdentifierExpr(v.tok, new VariableDualiser(Thread, null, null).VisitVariable(GPUVerifier.MakeOffsetXVariable(v, ReadOrWrite)));
}
- protected override void AddAccessedOffsetInRangeCTimesGlobalIdToCTimesGlobalIdPlusC(WhileCmd wc, Variable v, Expr constant, string ReadOrWrite)
+ protected override void AddAccessedOffsetInRangeCTimesGlobalIdToCTimesGlobalIdPlusC(IRegion region, Variable v, Expr constant, string ReadOrWrite)
{
Expr expr = MakeCTimesGloalIdRangeExpr(v, constant, ReadOrWrite, 1);
- verifier.AddCandidateInvariant(wc,
+ verifier.AddCandidateInvariant(region,
expr, "accessed offset in range [ C*global_id, (C+1)*global_id )");
}
diff --git a/Source/GPUVerify/GPUVerifier.cs b/Source/GPUVerify/GPUVerifier.cs index 4e30951e..1839b138 100644 --- a/Source/GPUVerify/GPUVerifier.cs +++ b/Source/GPUVerify/GPUVerifier.cs @@ -25,7 +25,7 @@ namespace GPUVerify private HashSet<string> ReservedNames = new HashSet<string>();
private int TempCounter = 0;
- private int invariantGenerationCounter;
+ private int invariantGenerationCounter = 0;
internal const string LOCAL_ID_X_STRING = "local_id_x";
internal const string LOCAL_ID_Y_STRING = "local_id_y";
@@ -64,13 +64,12 @@ namespace GPUVerify public UniformityAnalyser uniformityAnalyser;
public MayBeThreadConfigurationVariableAnalyser mayBeTidAnalyser;
public MayBeGidAnalyser mayBeGidAnalyser;
- public MayBeGlobalSizeAnalyser mayBeGlobalSizeAnalyser;
- public MayBeFlattened2DTidOrGidAnalyser mayBeFlattened2DTidOrGidAnalyser;
public MayBeLocalIdPlusConstantAnalyser mayBeTidPlusConstantAnalyser;
public MayBeGlobalIdPlusConstantAnalyser mayBeGidPlusConstantAnalyser;
public MayBePowerOfTwoAnalyser mayBePowerOfTwoAnalyser;
public LiveVariableAnalyser liveVariableAnalyser;
public ArrayControlFlowAnalyser arrayControlFlowAnalyser;
+ public Dictionary<Implementation, VariableDefinitionAnalysis> varDefAnalyses;
public GPUVerifier(string filename, Program program, ResolutionContext rc, IRaceInstrumenter raceInstrumenter) : this(filename, program, rc, raceInstrumenter, false)
{
@@ -124,6 +123,7 @@ namespace GPUVerify new EnsuresSeq(),
new QKeyValue(Token.NoToken, "barrier", new List<object>(), null));
Program.TopLevelDeclarations.Add(p);
+ ResContext.AddProcedure(p);
}
return p;
}
@@ -370,6 +370,8 @@ namespace GPUVerify DoArrayControlFlowAnalysis();
+ DoVariableDefinitionAnalysis();
+
if (CommandLineOptions.ShowStages)
{
emitProgram(outputFilename + "_preprocessed");
@@ -489,12 +491,6 @@ namespace GPUVerify mayBeGidAnalyser = new MayBeGidAnalyser(this);
mayBeGidAnalyser.Analyse();
-
- mayBeGlobalSizeAnalyser = new MayBeGlobalSizeAnalyser(this);
- mayBeGlobalSizeAnalyser.Analyse();
-
- mayBeFlattened2DTidOrGidAnalyser = new MayBeFlattened2DTidOrGidAnalyser(this);
- mayBeFlattened2DTidOrGidAnalyser.Analyse();
}
private void DoMayBeIdPlusConstantAnalysis()
@@ -523,6 +519,12 @@ namespace GPUVerify liveVariableAnalyser.Analyse();
}
+ private void DoVariableDefinitionAnalysis()
+ {
+ varDefAnalyses = Program.TopLevelDeclarations
+ .OfType<Implementation>()
+ .ToDictionary(i => i, i => VariableDefinitionAnalysis.Analyse(this, i));
+ }
private void ProcessAccessInvariants()
{
@@ -654,9 +656,6 @@ namespace GPUVerify private void ComputeInvariant()
{
-
- invariantGenerationCounter = 0;
-
for (int i = 0; i < Program.TopLevelDeclarations.Count; i++)
{
if (Program.TopLevelDeclarations[i] is Implementation)
@@ -1056,7 +1055,7 @@ namespace GPUVerify {
if (p.Contains("$"))
{
- return p.Substring(0, p.IndexOf("$"));
+ return p.Substring(0, p.LastIndexOf("$"));
}
return p;
}
@@ -1083,64 +1082,78 @@ namespace GPUVerify {
RaceInstrumenter.AddKernelPrecondition();
- Expr AssumeDistinctThreads = null;
- Expr AssumeThreadIdsInRange = null;
IToken tok = KernelImplementation.tok;
- GeneratePreconditionsForDimension(ref AssumeDistinctThreads, ref AssumeThreadIdsInRange, tok, "X");
- GeneratePreconditionsForDimension(ref AssumeDistinctThreads, ref AssumeThreadIdsInRange, tok, "Y");
- GeneratePreconditionsForDimension(ref AssumeDistinctThreads, ref AssumeThreadIdsInRange, tok, "Z");
+ GeneratePreconditionsForDimension(tok, "X");
+ GeneratePreconditionsForDimension(tok, "Y");
+ GeneratePreconditionsForDimension(tok, "Z");
- if (AssumeDistinctThreads != null)
+ foreach (Declaration D in Program.TopLevelDeclarations)
{
- Debug.Assert(AssumeThreadIdsInRange != null);
+ if (!(D is Procedure))
+ {
+ continue;
+ }
+ Procedure Proc = D as Procedure;
+ if (QKeyValue.FindIntAttribute(Proc.Attributes, "inline", -1) == 1)
+ {
+ continue;
+ }
+
+ Expr DistinctLocalIds =
+ Expr.Or(
+ Expr.Or(
+ Expr.Neq(
+ new IdentifierExpr(tok, MakeThreadId(tok, "X", 1)),
+ new IdentifierExpr(tok, MakeThreadId(tok, "X", 2))
+ ),
+ Expr.Neq(
+ new IdentifierExpr(tok, MakeThreadId(tok, "Y", 1)),
+ new IdentifierExpr(tok, MakeThreadId(tok, "Y", 2))
+ )
+ ),
+ Expr.Neq(
+ new IdentifierExpr(tok, MakeThreadId(tok, "Z", 1)),
+ new IdentifierExpr(tok, MakeThreadId(tok, "Z", 2))
+ )
+ );
- foreach (Declaration D in Program.TopLevelDeclarations)
+ if (CommandLineOptions.InterGroupRaceChecking)
{
- if (!(D is Procedure))
- {
- continue;
- }
- Procedure Proc = D as Procedure;
- if (QKeyValue.FindIntAttribute(Proc.Attributes, "inline", -1) == 1)
- {
- continue;
- }
+ Proc.Requires.Add(new Requires(false, Expr.Imp(ThreadsInSameGroup(), DistinctLocalIds)));
- Proc.Requires.Add(new Requires(false, AssumeDistinctThreads));
- Proc.Requires.Add(new Requires(false, AssumeThreadIdsInRange));
+ }
+ else
+ {
+ Proc.Requires.Add(new Requires(false, DistinctLocalIds));
+ }
- if (Proc == KernelProcedure)
+ if (Proc == KernelProcedure)
+ {
+ bool foundNonUniform = false;
+ int indexOfFirstNonUniformParameter;
+ for (indexOfFirstNonUniformParameter = 0; indexOfFirstNonUniformParameter < Proc.InParams.Length; indexOfFirstNonUniformParameter++)
{
- bool foundNonUniform = false;
- int indexOfFirstNonUniformParameter;
- for (indexOfFirstNonUniformParameter = 0; indexOfFirstNonUniformParameter < Proc.InParams.Length; indexOfFirstNonUniformParameter++)
+ if (!uniformityAnalyser.IsUniform(Proc.Name, StripThreadIdentifier(Proc.InParams[indexOfFirstNonUniformParameter].Name)))
{
- if (!uniformityAnalyser.IsUniform(Proc.Name, StripThreadIdentifier(Proc.InParams[indexOfFirstNonUniformParameter].Name)))
- {
- foundNonUniform = true;
- break;
- }
+ foundNonUniform = true;
+ break;
}
+ }
- if (foundNonUniform)
+ if (foundNonUniform)
+ {
+ // I have a feeling this will never be reachable!!!
+ int numberOfNonUniformParameters = (Proc.InParams.Length - indexOfFirstNonUniformParameter) / 2;
+ for (int i = indexOfFirstNonUniformParameter; i < numberOfNonUniformParameters; i++)
{
- // I have a feeling this will never be reachable!!!
- int numberOfNonUniformParameters = (Proc.InParams.Length - indexOfFirstNonUniformParameter) / 2;
- for (int i = indexOfFirstNonUniformParameter; i < numberOfNonUniformParameters; i++)
- {
- Proc.Requires.Add(new Requires(false,
- Expr.Eq(new IdentifierExpr(Proc.InParams[i].tok, Proc.InParams[i]),
- new IdentifierExpr(Proc.InParams[i + numberOfNonUniformParameters].tok, Proc.InParams[i + numberOfNonUniformParameters]))));
- }
+ Proc.Requires.Add(new Requires(false,
+ Expr.Eq(new IdentifierExpr(Proc.InParams[i].tok, Proc.InParams[i]),
+ new IdentifierExpr(Proc.InParams[i + numberOfNonUniformParameters].tok, Proc.InParams[i + numberOfNonUniformParameters]))));
}
}
-
}
- }
- else
- {
- Debug.Assert(AssumeThreadIdsInRange == null);
+
}
foreach (Declaration D in Program.TopLevelDeclarations)
@@ -1166,6 +1179,26 @@ namespace GPUVerify }
+ internal Expr ThreadsInSameGroup()
+ {
+ return Expr.And(
+ Expr.And(
+ Expr.Eq(
+ new IdentifierExpr(Token.NoToken, MakeGroupId("X", 1)),
+ new IdentifierExpr(Token.NoToken, MakeGroupId("X", 2))
+ ),
+ Expr.Eq(
+ new IdentifierExpr(Token.NoToken, MakeGroupId("Y", 1)),
+ new IdentifierExpr(Token.NoToken, MakeGroupId("Y", 2))
+ )
+ ),
+ Expr.Eq(
+ new IdentifierExpr(Token.NoToken, MakeGroupId("Z", 1)),
+ new IdentifierExpr(Token.NoToken, MakeGroupId("Z", 2))
+ )
+ );
+ }
+
internal static void AddInvariantToAllLoops(Expr Invariant, StmtList stmtList)
{
foreach (BigBlock bb in stmtList.BigBlocks)
@@ -1190,7 +1223,7 @@ namespace GPUVerify return Int32.Parse(p.Substring(p.IndexOf("$") + 1, p.Length - (p.IndexOf("$") + 1)));
}
- private void GeneratePreconditionsForDimension(ref Expr AssumeDistinctThreads, ref Expr AssumeThreadIdsInRange, IToken tok, String dimension)
+ private void GeneratePreconditionsForDimension(IToken tok, String dimension)
{
foreach (Declaration D in Program.TopLevelDeclarations.ToList())
{
@@ -1204,53 +1237,59 @@ namespace GPUVerify continue;
}
+ Expr GroupSizePositive;
+ Expr NumGroupsPositive;
+ Expr GroupIdNonNegative;
+ Expr GroupIdLessThanNumGroups;
+
if (GetTypeOfId(dimension).Equals(Microsoft.Boogie.Type.GetBvType(32)))
{
- Proc.Requires.Add(new Requires(false, MakeBVSgt(new IdentifierExpr(tok, GetGroupSize(dimension)), ZeroBV(tok))));
- Proc.Requires.Add(new Requires(false, MakeBVSgt(new IdentifierExpr(tok, GetNumGroups(dimension)), ZeroBV(tok))));
- Proc.Requires.Add(new Requires(false, MakeBVSge(new IdentifierExpr(tok, GetGroupId(dimension)), ZeroBV(tok))));
- Proc.Requires.Add(new Requires(false, MakeBVSlt(new IdentifierExpr(tok, GetGroupId(dimension)), new IdentifierExpr(tok, GetNumGroups(dimension)))));
+ GroupSizePositive = MakeBVSgt(new IdentifierExpr(tok, GetGroupSize(dimension)), ZeroBV(tok));
+ NumGroupsPositive = MakeBVSgt(new IdentifierExpr(tok, GetNumGroups(dimension)), ZeroBV(tok));
+ GroupIdNonNegative = MakeBVSge(new IdentifierExpr(tok, GetGroupId(dimension)), ZeroBV(tok));
+ GroupIdLessThanNumGroups = MakeBVSlt(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)))));
+ GroupSizePositive = Expr.Gt(new IdentifierExpr(tok, GetGroupSize(dimension)), Zero(tok));
+ NumGroupsPositive = Expr.Gt(new IdentifierExpr(tok, GetNumGroups(dimension)), Zero(tok));
+ GroupIdNonNegative = Expr.Ge(new IdentifierExpr(tok, GetGroupId(dimension)), Zero(tok));
+ GroupIdLessThanNumGroups = 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))
- );
+ Proc.Requires.Add(new Requires(false, GroupSizePositive));
+ Proc.Requires.Add(new Requires(false, NumGroupsPositive));
+ if (CommandLineOptions.InterGroupRaceChecking)
+ {
+ Proc.Requires.Add(new Requires(false, new VariableDualiser(1, null, null).VisitExpr(GroupIdNonNegative)));
+ Proc.Requires.Add(new Requires(false, new VariableDualiser(2, null, null).VisitExpr(GroupIdNonNegative)));
+ Proc.Requires.Add(new Requires(false, new VariableDualiser(1, null, null).VisitExpr(GroupIdLessThanNumGroups)));
+ Proc.Requires.Add(new Requires(false, new VariableDualiser(2, null, null).VisitExpr(GroupIdLessThanNumGroups)));
+ }
+ else
+ {
+ Proc.Requires.Add(new Requires(false, GroupIdNonNegative));
+ Proc.Requires.Add(new Requires(false, GroupIdLessThanNumGroups));
+ }
- AssumeDistinctThreads = (null == AssumeDistinctThreads) ? AssumeThreadsDistinctInDimension : Expr.Or(AssumeDistinctThreads, AssumeThreadsDistinctInDimension);
+ Expr ThreadIdNonNegative =
+ GetTypeOfId(dimension).Equals(Microsoft.Boogie.Type.GetBvType(32)) ?
+ MakeBVSge(new IdentifierExpr(tok, MakeThreadId(tok, dimension)), ZeroBV(tok))
+ :
+ Expr.Ge(new IdentifierExpr(tok, MakeThreadId(tok, dimension)), Zero(tok));
+ Expr ThreadIdLessThanGroupSize =
+ GetTypeOfId(dimension).Equals(Microsoft.Boogie.Type.GetBvType(32)) ?
+ MakeBVSlt(new IdentifierExpr(tok, MakeThreadId(tok, dimension)), new IdentifierExpr(tok, GetGroupSize(dimension)))
+ :
+ Expr.Lt(new IdentifierExpr(tok, MakeThreadId(tok, dimension)), new IdentifierExpr(tok, GetGroupSize(dimension)));
- Expr AssumeThreadIdsInRangeInDimension =
- GetTypeOfId(dimension).Equals(Microsoft.Boogie.Type.GetBvType(32)) ?
- Expr.And(
- Expr.And(
- MakeBVSge(new IdentifierExpr(tok, MakeThreadId(tok, dimension, 1)), ZeroBV(tok)),
- MakeBVSge(new IdentifierExpr(tok, MakeThreadId(tok, dimension, 2)), ZeroBV(tok))
- ),
- Expr.And(
- MakeBVSlt(new IdentifierExpr(tok, MakeThreadId(tok, dimension, 1)), new IdentifierExpr(tok, GetGroupSize(dimension))),
- MakeBVSlt(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)))
- ));
+ Proc.Requires.Add(new Requires(false, new VariableDualiser(1, null, null).VisitExpr(ThreadIdNonNegative)));
+ Proc.Requires.Add(new Requires(false, new VariableDualiser(2, null, null).VisitExpr(ThreadIdNonNegative)));
+ Proc.Requires.Add(new Requires(false, new VariableDualiser(1, null, null).VisitExpr(ThreadIdLessThanGroupSize)));
+ Proc.Requires.Add(new Requires(false, new VariableDualiser(2, null, null).VisitExpr(ThreadIdLessThanGroupSize)));
+
+ }
- AssumeThreadIdsInRange = (null == AssumeThreadIdsInRange) ? AssumeThreadIdsInRangeInDimension : Expr.And(AssumeThreadIdsInRange, AssumeThreadIdsInRangeInDimension);
}
private Function GetOrCreateBVFunction(string functionName, string smtName, Microsoft.Boogie.Type resultType, params Microsoft.Boogie.Type[] argTypes)
@@ -1351,6 +1390,12 @@ namespace GPUVerify return null;
}
+ internal Constant MakeGroupId(string dimension, int number)
+ {
+ Constant resultWithoutThreadId = GetGroupId(dimension);
+ return new Constant(Token.NoToken, new TypedIdent(Token.NoToken, resultWithoutThreadId.Name + "$" + number, GetTypeOfId(dimension)));
+ }
+
private static LiteralExpr Zero(IToken tok)
{
return new LiteralExpr(tok, BigNum.FromInt(0));
@@ -1374,8 +1419,13 @@ namespace GPUVerify IdentifierExpr P1 = new IdentifierExpr(tok, new LocalVariable(tok, BarrierProcedure.InParams[0].TypedIdent));
IdentifierExpr P2 = new IdentifierExpr(tok, new LocalVariable(tok, BarrierProcedure.InParams[1].TypedIdent));
- if (!CommandLineOptions.Unstructured)
- checkNonDivergence.simpleCmds.Add(new AssertCmd(tok, Expr.Eq(P1, P2)));
+ Expr DivergenceCondition = Expr.Eq(P1, P2);
+ if (CommandLineOptions.InterGroupRaceChecking)
+ {
+ DivergenceCondition = Expr.Imp(ThreadsInSameGroup(), DivergenceCondition);
+ }
+
+ checkNonDivergence.simpleCmds.Add(new AssertCmd(tok, DivergenceCondition));
if (!CommandLineOptions.OnlyDivergence)
{
@@ -1388,15 +1438,32 @@ namespace GPUVerify checkNonDivergence.ec = new IfCmd(tok, Expr.Or(Expr.Not(P1), Expr.Not(P2)), returnstatement, null, null);
}
- bigblocks.Add(RaceInstrumenter.MakeResetReadWriteSetsStatements(tok));
+ if (CommandLineOptions.InterGroupRaceChecking)
+ {
+ bigblocks.Add(new BigBlock(Token.NoToken, null, new CmdSeq(),
+ new IfCmd(Token.NoToken, P1, new StmtList(MakeResetAndHavocBlocks(1), Token.NoToken), null, null),
+ null));
+ bigblocks.Add(new BigBlock(Token.NoToken, null, new CmdSeq(),
+ new IfCmd(Token.NoToken, P2, new StmtList(MakeResetAndHavocBlocks(2), Token.NoToken), null, null),
+ null));
+ }
+ else
+ {
+ foreach (BigBlock bb in MakeResetAndHavocBlocks(1))
+ {
+ bigblocks.Add(bb);
+ }
+ foreach (BigBlock bb in MakeResetAndHavocBlocks(2))
+ {
+ bigblocks.Add(bb);
+ }
+ }
- BigBlock havocSharedState = new BigBlock(tok, "__HavocSharedState", new CmdSeq(), null, null);
- bigblocks.Add(havocSharedState);
foreach (Variable v in NonLocalState.getAllNonLocalVariables())
{
if (!ArrayModelledAdversarially(v))
{
- HavocAndAssumeEquality(tok, havocSharedState, v);
+ bigblocks.Add(AssumeEqualityBetweenSharedArrays(v, P1, P2));
}
}
@@ -1414,6 +1481,20 @@ namespace GPUVerify Program.TopLevelDeclarations.Add(BarrierImplementation);
}
+ private List<BigBlock> MakeResetAndHavocBlocks(int Thread)
+ {
+ List<BigBlock> ResetAndHavocBlocks = new List<BigBlock>();
+ foreach (Variable v in NonLocalState.getAllNonLocalVariables())
+ {
+ ResetAndHavocBlocks.Add(RaceInstrumenter.MakeResetReadWriteSetStatements(v, Thread));
+ if (!ArrayModelledAdversarially(v))
+ {
+ ResetAndHavocBlocks.Add(HavocSharedArray(v, Thread));
+ }
+ }
+ return ResetAndHavocBlocks;
+ }
+
public static bool HasZDimension(Variable v)
{
@@ -1444,17 +1525,28 @@ namespace GPUVerify return v.TypedIdent.Type is MapType;
}
- private void HavocAndAssumeEquality(IToken tok, BigBlock bb, Variable v)
+ private BigBlock HavocSharedArray(Variable v, int thread)
{
- IdentifierExpr v1 = new IdentifierExpr(tok, new VariableDualiser(1, null, null).VisitVariable(v.Clone() as Variable));
- IdentifierExpr v2 = new IdentifierExpr(tok, new VariableDualiser(2, null, null).VisitVariable(v.Clone() as Variable));
+ IdentifierExpr vForThread = new IdentifierExpr(Token.NoToken, new VariableDualiser(thread, null, null).VisitVariable(v.Clone() as Variable));
+ return new BigBlock(Token.NoToken, null, new CmdSeq(new Cmd[] { new HavocCmd(Token.NoToken, new IdentifierExprSeq(new IdentifierExpr[] { vForThread })) }), null, null);
+ }
- IdentifierExprSeq ModifiedVars = new IdentifierExprSeq(new IdentifierExpr[] { v1, v2 });
- bb.simpleCmds.Add(new HavocCmd(tok, ModifiedVars));
- bb.simpleCmds.Add(new AssumeCmd(tok, Expr.Eq(v1, v2)));
+ private BigBlock AssumeEqualityBetweenSharedArrays(Variable v, Expr P1, Expr P2)
+ {
+ IdentifierExpr v1 = new IdentifierExpr(Token.NoToken, new VariableDualiser(1, null, null).VisitVariable(v.Clone() as Variable));
+ IdentifierExpr v2 = new IdentifierExpr(Token.NoToken, new VariableDualiser(2, null, null).VisitVariable(v.Clone() as Variable));
+ Expr AssumeGuard = Expr.Eq(v1, v2);
+
+ if (CommandLineOptions.InterGroupRaceChecking)
+ {
+ AssumeGuard = Expr.Imp(ThreadsInSameGroup(), AssumeGuard);
+ }
+
+ return new BigBlock(Token.NoToken, null, new CmdSeq(new Cmd[] { new AssumeCmd(Token.NoToken, AssumeGuard) }), null, null);
}
+
internal static bool ModifiesSetContains(IdentifierExprSeq Modifies, IdentifierExpr v)
{
foreach (IdentifierExpr ie in Modifies)
@@ -2040,7 +2132,8 @@ namespace GPUVerify }
- if (d is Variable && ((d as Variable).IsMutable || IsThreadLocalIdConstant(d as Variable)))
+ if (d is Variable && ((d as Variable).IsMutable || IsThreadLocalIdConstant(d as Variable)
+ || (CommandLineOptions.InterGroupRaceChecking && IsGroupIdConstant(d as Variable) ) ))
{
NewTopLevelDeclarations.Add(new VariableDualiser(1, null, null).VisitVariable((Variable)d.Clone()));
NewTopLevelDeclarations.Add(new VariableDualiser(2, null, null).VisitVariable((Variable)d.Clone()));
@@ -2060,7 +2153,7 @@ namespace GPUVerify {
if (CommandLineOptions.Unstructured)
{
- BlockPredicator.Predicate(Program);
+ BlockPredicator.Predicate(this, Program);
return;
}
@@ -2157,16 +2250,26 @@ namespace GPUVerify return variable.Name.Equals(_X.Name) || variable.Name.Equals(_Y.Name) || variable.Name.Equals(_Z.Name);
}
- internal void AddCandidateInvariant(WhileCmd wc, Expr e, string tag)
+ public static bool IsGroupIdConstant(Variable variable)
+ {
+ return variable.Name.Equals(_GROUP_X.Name) || variable.Name.Equals(_GROUP_Y.Name) || variable.Name.Equals(_GROUP_Z.Name);
+ }
+
+ internal void AddCandidateInvariant(IRegion region, Expr e, string tag)
+ {
+ region.AddInvariant(CreateCandidateInvariant(e, tag));
+ }
+
+ internal PredicateCmd CreateCandidateInvariant(Expr e, string tag)
{
- Constant ExistentialBooleanConstant = MakeExistentialBoolean(wc.tok);
- IdentifierExpr ExistentialBoolean = new IdentifierExpr(wc.tok, ExistentialBooleanConstant);
- PredicateCmd invariant = new AssertCmd(wc.tok, Expr.Imp(ExistentialBoolean, e));
+ Constant ExistentialBooleanConstant = MakeExistentialBoolean(Token.NoToken);
+ IdentifierExpr ExistentialBoolean = new IdentifierExpr(Token.NoToken, ExistentialBooleanConstant);
+ PredicateCmd invariant = new AssertCmd(Token.NoToken, Expr.Imp(ExistentialBoolean, e));
invariant.Attributes = new QKeyValue(Token.NoToken, "tag", new List<object>(new object[] { tag }), null);
- wc.Invariants.Add(invariant);
Program.TopLevelDeclarations.Add(ExistentialBooleanConstant);
+ return invariant;
}
-
+
internal Implementation GetImplementation(string procedureName)
{
foreach (Declaration D in Program.TopLevelDeclarations)
@@ -2181,21 +2284,9 @@ namespace GPUVerify }
- internal bool ContainsBarrierCall(StmtList stmtList)
+ internal bool ContainsBarrierCall(IRegion loop)
{
- foreach (BigBlock bb in stmtList.BigBlocks)
- {
- if (ContainsBarrierCall(bb))
- {
- return true;
- }
- }
- return false;
- }
-
- private bool ContainsBarrierCall(BigBlock bb)
- {
- foreach (Cmd c in bb.simpleCmds)
+ foreach (Cmd c in loop.Cmds())
{
if (c is CallCmd && ((c as CallCmd).Proc == BarrierProcedure))
{
@@ -2203,21 +2294,6 @@ namespace GPUVerify }
}
- if (bb.ec is WhileCmd)
- {
- return ContainsBarrierCall((bb.ec as WhileCmd).Body);
- }
-
- if (bb.ec is IfCmd)
- {
- Debug.Assert((bb.ec as IfCmd).elseIf == null);
- if (ContainsBarrierCall((bb.ec as IfCmd).thn))
- {
- return true;
- }
- return (bb.ec as IfCmd).elseBlock != null && ContainsBarrierCall((bb.ec as IfCmd).elseBlock);
- }
-
return false;
}
@@ -2247,6 +2323,14 @@ namespace GPUVerify new IdentifierExpr(Token.NoToken, GetGroupId(dimension)), new IdentifierExpr(Token.NoToken, GetGroupSize(dimension))),
new IdentifierExpr(Token.NoToken, MakeThreadId(Token.NoToken, dimension)));
}
+
+ internal IRegion RootRegion(Implementation Impl)
+ {
+ if (CommandLineOptions.Unstructured)
+ return new UnstructuredRegion(Program, Impl);
+ else
+ return new StructuredRegion(Impl);
+ }
}
class ThreadIdentifierStripper : StandardVisitor
diff --git a/Source/GPUVerify/GPUVerify.csproj b/Source/GPUVerify/GPUVerify.csproj index 27b9abe5..0c87587f 100644 --- a/Source/GPUVerify/GPUVerify.csproj +++ b/Source/GPUVerify/GPUVerify.csproj @@ -109,12 +109,12 @@ <Compile Include="ArrayControlFlowAnalyser.cs" />
<Compile Include="AsymmetricExpressionFinder.cs" />
<Compile Include="BlockPredicator.cs" />
+ <Compile Include="UnstructuredRegion.cs" />
+ <Compile Include="IRegion.cs" />
<Compile Include="GraphAlgorithms.cs" />
<Compile Include="InvariantGenerationRules\LoopVariableBoundsInvariantGenerator.cs" />
<Compile Include="InvariantGenerationRules\InvariantGenerationRule.cs" />
<Compile Include="InvariantGenerationRules\PowerOfTwoInvariantGenerator.cs" />
- <Compile Include="MayBeGlobalSizeAnalyser.cs" />
- <Compile Include="MayBeFlattened2DTidOrGidAnalyser.cs" />
<Compile Include="MayBeGidAnalyser.cs" />
<Compile Include="EnsureDisabledThreadHasNoEffectInstrumenter.cs" />
<Compile Include="KernelDualiser.cs" />
@@ -145,6 +145,8 @@ <Compile Include="UniformityAnalyser.cs" />
<Compile Include="VariableDualiser.cs" />
<Compile Include="VariablesOccurringInExpressionVisitor.cs" />
+ <Compile Include="VariableDefinitionAnalysis.cs" />
+ <Compile Include="StructuredRegion.cs" />
<Compile Include="WriteCollector.cs" />
</ItemGroup>
<ItemGroup>
diff --git a/Source/GPUVerify/IRaceInstrumenter.cs b/Source/GPUVerify/IRaceInstrumenter.cs index 65d2cc1b..63b1ea1a 100644 --- a/Source/GPUVerify/IRaceInstrumenter.cs +++ b/Source/GPUVerify/IRaceInstrumenter.cs @@ -8,7 +8,7 @@ namespace GPUVerify {
interface IRaceInstrumenter
{
- void AddRaceCheckingCandidateInvariants(Implementation impl, WhileCmd wc);
+ void AddRaceCheckingCandidateInvariants(Implementation impl, IRegion region);
void AddKernelPrecondition();
// Summary:
@@ -20,7 +20,7 @@ namespace GPUVerify void AddRaceCheckingDeclarations();
- BigBlock MakeResetReadWriteSetsStatements(IToken tok);
+ BigBlock MakeResetReadWriteSetStatements(Variable v, int thread);
void AddRaceCheckingCandidateRequires(Procedure Proc);
diff --git a/Source/GPUVerify/IRegion.cs b/Source/GPUVerify/IRegion.cs new file mode 100644 index 00000000..c6655b06 --- /dev/null +++ b/Source/GPUVerify/IRegion.cs @@ -0,0 +1,18 @@ +using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Microsoft.Boogie;
+
+namespace GPUVerify {
+
+interface IRegion {
+ object Identifier();
+ IEnumerable<Cmd> Cmds();
+ IEnumerable<object> CmdsChildRegions();
+ IEnumerable<IRegion> SubRegions();
+ Expr Guard();
+ void AddInvariant(PredicateCmd pc);
+}
+
+}
diff --git a/Source/GPUVerify/InvariantGenerationRules/InvariantGenerationRule.cs b/Source/GPUVerify/InvariantGenerationRules/InvariantGenerationRule.cs index 1bd66785..cb2a9f41 100644 --- a/Source/GPUVerify/InvariantGenerationRules/InvariantGenerationRule.cs +++ b/Source/GPUVerify/InvariantGenerationRules/InvariantGenerationRule.cs @@ -16,7 +16,7 @@ namespace GPUVerify.InvariantGenerationRules this.verifier = verifier;
}
- public abstract void GenerateCandidates(Implementation Impl, WhileCmd wc);
+ public abstract void GenerateCandidates(Implementation Impl, IRegion region);
}
}
diff --git a/Source/GPUVerify/InvariantGenerationRules/LoopVariableBoundsInvariantGenerator.cs b/Source/GPUVerify/InvariantGenerationRules/LoopVariableBoundsInvariantGenerator.cs index af5f8d71..f73bddb6 100644 --- a/Source/GPUVerify/InvariantGenerationRules/LoopVariableBoundsInvariantGenerator.cs +++ b/Source/GPUVerify/InvariantGenerationRules/LoopVariableBoundsInvariantGenerator.cs @@ -17,15 +17,15 @@ namespace GPUVerify.InvariantGenerationRules }
- public override void GenerateCandidates(Implementation Impl, WhileCmd wc)
+ public override void GenerateCandidates(Implementation Impl, IRegion region)
{
- if (verifier.uniformityAnalyser.IsUniform(Impl.Name, wc.Guard))
+ if (verifier.uniformityAnalyser.IsUniform(Impl.Name, region.Guard()))
{
VariablesOccurringInExpressionVisitor visitor = new VariablesOccurringInExpressionVisitor();
- visitor.VisitExpr(wc.Guard);
+ visitor.VisitExpr(region.Guard());
foreach (Variable v in visitor.GetVariables())
{
- if (!verifier.ContainsNamedVariable(LoopInvariantGenerator.GetModifiedVariables(wc.Body), v.Name))
+ if (!verifier.ContainsNamedVariable(LoopInvariantGenerator.GetModifiedVariables(region), v.Name))
{
continue;
}
@@ -34,7 +34,7 @@ namespace GPUVerify.InvariantGenerationRules {
int BVWidth = (v.TypedIdent.Type as BvType).Bits;
- verifier.AddCandidateInvariant(wc,
+ verifier.AddCandidateInvariant(region,
verifier.MakeBVSge(
new IdentifierExpr(v.tok, v),
new LiteralExpr(v.tok, BigNum.FromInt(0), BVWidth)), "loop guard variable non-negative");
diff --git a/Source/GPUVerify/InvariantGenerationRules/PowerOfTwoInvariantGenerator.cs b/Source/GPUVerify/InvariantGenerationRules/PowerOfTwoInvariantGenerator.cs index 6b2bdc56..8b24bb0a 100644 --- a/Source/GPUVerify/InvariantGenerationRules/PowerOfTwoInvariantGenerator.cs +++ b/Source/GPUVerify/InvariantGenerationRules/PowerOfTwoInvariantGenerator.cs @@ -17,7 +17,7 @@ namespace GPUVerify.InvariantGenerationRules }
- public override void GenerateCandidates(Implementation Impl, WhileCmd wc)
+ public override void GenerateCandidates(Implementation Impl, IRegion region)
{
foreach (Variable v in Impl.LocVars)
{
@@ -26,17 +26,17 @@ namespace GPUVerify.InvariantGenerationRules {
if (verifier.mayBePowerOfTwoAnalyser.MayBePowerOfTwo(Impl.Name, basicName))
{
- if (verifier.ContainsNamedVariable(LoopInvariantGenerator.GetModifiedVariables(wc.Body), basicName))
+ if (verifier.ContainsNamedVariable(LoopInvariantGenerator.GetModifiedVariables(region), basicName))
{
- verifier.AddCandidateInvariant(wc, MakePowerOfTwoExpr(v), "pow2 disjunction");
+ verifier.AddCandidateInvariant(region, MakePowerOfTwoExpr(v), "pow2 disjunction");
for (int i = (1 << 15); i > 0; i >>= 1)
{
- verifier.AddCandidateInvariant(wc,
+ verifier.AddCandidateInvariant(region,
GPUVerifier.MakeBitVectorBinaryBoolean("BV32_LT",
new IdentifierExpr(v.tok, v),
new LiteralExpr(v.tok, BigNum.FromInt(i), 32)), "pow2 less than " + i);
}
- verifier.AddCandidateInvariant(wc,
+ verifier.AddCandidateInvariant(region,
Expr.Neq(new IdentifierExpr(v.tok, v),
new LiteralExpr(v.tok, BigNum.FromInt(0), 32)), "pow2 not zero");
}
diff --git a/Source/GPUVerify/KernelDualiser.cs b/Source/GPUVerify/KernelDualiser.cs index 49b04251..967b69ef 100644 --- a/Source/GPUVerify/KernelDualiser.cs +++ b/Source/GPUVerify/KernelDualiser.cs @@ -186,27 +186,27 @@ namespace GPUVerify else if (c is AssertCmd)
{
AssertCmd ass = c as AssertCmd;
- if (ContainsAsymmetricExpression(ass.Expr))
+ cs.Add(new AssertCmd(c.tok, new VariableDualiser(1, verifier.uniformityAnalyser, procName).VisitExpr(ass.Expr.Clone() as Expr), ass.Attributes));
+ if (!ContainsAsymmetricExpression(ass.Expr))
{
- cs.Add(new AssertCmd(c.tok, new VariableDualiser(1, verifier.uniformityAnalyser, procName).VisitExpr(ass.Expr.Clone() as Expr)));
- }
- else
- {
- cs.Add(new AssertCmd(c.tok, Expr.And(new VariableDualiser(1, verifier.uniformityAnalyser, procName).VisitExpr(ass.Expr.Clone() as Expr),
- new VariableDualiser(2, verifier.uniformityAnalyser, procName).VisitExpr(ass.Expr.Clone() as Expr))));
+ cs.Add(new AssertCmd(c.tok, new VariableDualiser(2, verifier.uniformityAnalyser, procName).VisitExpr(ass.Expr.Clone() as Expr), ass.Attributes));
}
}
else if (c is AssumeCmd)
{
AssumeCmd ass = c as AssumeCmd;
- if (ContainsAsymmetricExpression(ass.Expr))
+ if (QKeyValue.FindBoolAttribute(ass.Attributes, "backedge"))
{
- cs.Add(new AssumeCmd(c.tok, new VariableDualiser(1, verifier.uniformityAnalyser, procName).VisitExpr(ass.Expr.Clone() as Expr)));
+ cs.Add(new AssumeCmd(c.tok, Expr.Or(new VariableDualiser(1, verifier.uniformityAnalyser, procName).VisitExpr(ass.Expr.Clone() as Expr),
+ new VariableDualiser(2, verifier.uniformityAnalyser, procName).VisitExpr(ass.Expr.Clone() as Expr))));
}
else
{
- cs.Add(new AssumeCmd(c.tok, Expr.And(new VariableDualiser(1, verifier.uniformityAnalyser, procName).VisitExpr(ass.Expr.Clone() as Expr),
- new VariableDualiser(2, verifier.uniformityAnalyser, procName).VisitExpr(ass.Expr.Clone() as Expr))));
+ cs.Add(new AssumeCmd(c.tok, new VariableDualiser(1, verifier.uniformityAnalyser, procName).VisitExpr(ass.Expr.Clone() as Expr)));
+ if (!ContainsAsymmetricExpression(ass.Expr))
+ {
+ cs.Add(new AssumeCmd(c.tok, new VariableDualiser(2, verifier.uniformityAnalyser, procName).VisitExpr(ass.Expr.Clone() as Expr)));
+ }
}
}
else
@@ -268,12 +268,13 @@ namespace GPUVerify private Block MakeDual(Block b)
{
- Block result = new Block(b.tok, b.Label, new CmdSeq(), b.TransferCmd);
+ var newCmds = new CmdSeq();
foreach (Cmd c in b.Cmds)
{
- MakeDual(result.Cmds, c);
+ MakeDual(newCmds, c);
}
- return result;
+ b.Cmds = newCmds;
+ return b;
}
private List<PredicateCmd> MakeDualInvariants(List<PredicateCmd> originalInvariants)
diff --git a/Source/GPUVerify/LoopInvariantGenerator.cs b/Source/GPUVerify/LoopInvariantGenerator.cs index ead78917..936d1c44 100644 --- a/Source/GPUVerify/LoopInvariantGenerator.cs +++ b/Source/GPUVerify/LoopInvariantGenerator.cs @@ -43,153 +43,131 @@ namespace GPUVerify LocalVars.Add(v);
}
- AddCandidateInvariants(Impl.StructuredStmts, LocalVars, UserSuppliedInvariants, Impl);
+ AddCandidateInvariants(verifier.RootRegion(Impl), LocalVars, UserSuppliedInvariants, Impl);
}
- private void AddEqualityCandidateInvariant(WhileCmd wc, string LoopPredicate, Variable v)
+ private void AddEqualityCandidateInvariant(IRegion region, string LoopPredicate, Variable v)
{
- verifier.AddCandidateInvariant(wc,
+ verifier.AddCandidateInvariant(region,
Expr.Eq(
- new IdentifierExpr(wc.tok, new VariableDualiser(1, verifier.uniformityAnalyser, Impl.Name).VisitVariable(v.Clone() as Variable)),
- new IdentifierExpr(wc.tok, new VariableDualiser(2, verifier.uniformityAnalyser, Impl.Name).VisitVariable(v.Clone() as Variable))
+ new IdentifierExpr(Token.NoToken, new VariableDualiser(1, verifier.uniformityAnalyser, Impl.Name).VisitVariable(v.Clone() as Variable)),
+ new IdentifierExpr(Token.NoToken, new VariableDualiser(2, verifier.uniformityAnalyser, Impl.Name).VisitVariable(v.Clone() as Variable))
), "equality");
}
- private void AddPredicatedEqualityCandidateInvariant(WhileCmd wc, string LoopPredicate, Variable v)
+ private void AddPredicatedEqualityCandidateInvariant(IRegion region, string LoopPredicate, Variable v)
{
- verifier.AddCandidateInvariant(wc, Expr.Imp(
+ verifier.AddCandidateInvariant(region, Expr.Imp(
Expr.And(
- new IdentifierExpr(wc.tok, new LocalVariable(wc.tok, new TypedIdent(wc.tok, LoopPredicate + "$1", Microsoft.Boogie.Type.Int))),
- new IdentifierExpr(wc.tok, new LocalVariable(wc.tok, new TypedIdent(wc.tok, LoopPredicate + "$2", Microsoft.Boogie.Type.Int)))
+ new IdentifierExpr(Token.NoToken, new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, LoopPredicate + "$1", Microsoft.Boogie.Type.Int))),
+ new IdentifierExpr(Token.NoToken, new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, LoopPredicate + "$2", Microsoft.Boogie.Type.Int)))
),
Expr.Eq(
- new IdentifierExpr(wc.tok, new VariableDualiser(1, verifier.uniformityAnalyser, Impl.Name).VisitVariable(v.Clone() as Variable)),
- new IdentifierExpr(wc.tok, new VariableDualiser(2, verifier.uniformityAnalyser, Impl.Name).VisitVariable(v.Clone() as Variable))
+ new IdentifierExpr(Token.NoToken, new VariableDualiser(1, verifier.uniformityAnalyser, Impl.Name).VisitVariable(v.Clone() as Variable)),
+ new IdentifierExpr(Token.NoToken, new VariableDualiser(2, verifier.uniformityAnalyser, Impl.Name).VisitVariable(v.Clone() as Variable))
)), "predicated equality");
}
- private void AddBarrierDivergenceCandidates(HashSet<Variable> LocalVars, Implementation Impl, WhileCmd wc)
+ private void AddBarrierDivergenceCandidates(HashSet<Variable> LocalVars, Implementation Impl, IRegion region)
{
if (CommandLineOptions.AddDivergenceCandidatesOnlyToBarrierLoops)
{
- if (!verifier.ContainsBarrierCall(wc.Body))
+ if (!verifier.ContainsBarrierCall(region))
{
return;
}
}
- if (verifier.uniformityAnalyser.IsUniform(Impl.Name, wc.Guard))
+ Expr guard = region.Guard();
+ if (verifier.uniformityAnalyser.IsUniform(Impl.Name, guard))
{
return;
}
- Debug.Assert(wc.Guard is NAryExpr);
- Debug.Assert((wc.Guard as NAryExpr).Args.Length == 2);
- Debug.Assert((wc.Guard as NAryExpr).Args[0] is IdentifierExpr);
- string LoopPredicate = ((wc.Guard as NAryExpr).Args[0] as IdentifierExpr).Name;
-
- LoopPredicate = LoopPredicate.Substring(0, LoopPredicate.IndexOf('$'));
+ if (guard is NAryExpr &&
+ (guard as NAryExpr).Args.Length == 2 &&
+ (guard as NAryExpr).Args[0] is IdentifierExpr)
+ {
+ string LoopPredicate = ((guard as NAryExpr).Args[0] as IdentifierExpr).Name;
- verifier.AddCandidateInvariant(wc, Expr.Eq(
- // Int type used here, but it doesn't matter as we will print and then re-parse the program
- new IdentifierExpr(wc.tok, new LocalVariable(wc.tok, new TypedIdent(wc.tok, LoopPredicate + "$1", Microsoft.Boogie.Type.Int))),
- new IdentifierExpr(wc.tok, new LocalVariable(wc.tok, new TypedIdent(wc.tok, LoopPredicate + "$2", Microsoft.Boogie.Type.Int)))
- ), "loop predicate equality");
+ LoopPredicate = LoopPredicate.Substring(0, LoopPredicate.IndexOf('$'));
- foreach (Variable v in LocalVars)
- {
+ verifier.AddCandidateInvariant(region, Expr.Eq(
+ // Int type used here, but it doesn't matter as we will print and then re-parse the program
+ new IdentifierExpr(Token.NoToken, new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, LoopPredicate + "$1", Microsoft.Boogie.Type.Int))),
+ new IdentifierExpr(Token.NoToken, new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, LoopPredicate + "$2", Microsoft.Boogie.Type.Int)))
+ ), "loop predicate equality");
- if (verifier.uniformityAnalyser.IsUniform(Impl.Name, v.Name))
+ foreach (Variable v in LocalVars)
{
- continue;
- }
- string lv = GPUVerifier.StripThreadIdentifier(v.Name);
+ if (verifier.uniformityAnalyser.IsUniform(Impl.Name, v.Name))
+ {
+ continue;
+ }
- if (GPUVerifier.IsPredicateOrTemp(lv))
- {
- continue;
- }
+ string lv = GPUVerifier.StripThreadIdentifier(v.Name);
- if (CommandLineOptions.AddDivergenceCandidatesOnlyIfModified)
- {
- if (!verifier.ContainsNamedVariable(GetModifiedVariables(wc.Body),
- GPUVerifier.StripThreadIdentifier(v.Name)))
+ if (GPUVerifier.IsPredicateOrTemp(lv))
{
continue;
}
- }
- AddEqualityCandidateInvariant(wc, LoopPredicate, new LocalVariable(wc.tok, new TypedIdent(wc.tok, lv, Microsoft.Boogie.Type.Int)));
+ if (CommandLineOptions.AddDivergenceCandidatesOnlyIfModified)
+ {
+ if (!verifier.ContainsNamedVariable(GetModifiedVariables(region),
+ GPUVerifier.StripThreadIdentifier(v.Name)))
+ {
+ continue;
+ }
+ }
+
+ AddEqualityCandidateInvariant(region, LoopPredicate, new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, lv, Microsoft.Boogie.Type.Int)));
- if (Impl != verifier.KernelImplementation)
- {
- AddPredicatedEqualityCandidateInvariant(wc, LoopPredicate, new LocalVariable(wc.tok, new TypedIdent(wc.tok, lv, Microsoft.Boogie.Type.Int)));
+ if (Impl != verifier.KernelImplementation)
+ {
+ AddPredicatedEqualityCandidateInvariant(region, LoopPredicate, new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, lv, Microsoft.Boogie.Type.Int)));
+ }
}
- }
- if (CommandLineOptions.ArrayEqualities)
- {
- foreach (Variable v in verifier.NonLocalState.getAllNonLocalVariables())
+ if (CommandLineOptions.ArrayEqualities)
{
- if (!verifier.ArrayModelledAdversarially(v))
+ foreach (Variable v in verifier.NonLocalState.getAllNonLocalVariables())
{
- AddEqualityCandidateInvariant(wc, LoopPredicate, v);
+ if (!verifier.ArrayModelledAdversarially(v))
+ {
+ AddEqualityCandidateInvariant(region, LoopPredicate, v);
+ }
}
}
}
}
- private void AddCandidateInvariants(StmtList stmtList, HashSet<Variable> LocalVars, List<Expr> UserSuppliedInvariants, Implementation Impl)
- {
- foreach (BigBlock bb in stmtList.BigBlocks)
- {
- AddCandidateInvariants(bb, LocalVars, UserSuppliedInvariants, Impl);
- }
- }
-
- private void AddCandidateInvariants(BigBlock bb, HashSet<Variable> LocalVars, List<Expr> UserSuppliedInvariants, Implementation Impl)
+ private void AddCandidateInvariants(IRegion region, HashSet<Variable> LocalVars, List<Expr> UserSuppliedInvariants, Implementation Impl)
{
- if (bb.ec is WhileCmd)
+ foreach (IRegion subregion in region.SubRegions())
{
- WhileCmd wc = bb.ec as WhileCmd;
-
foreach (InvariantGenerationRule r in invariantGenerationRules)
{
- r.GenerateCandidates(Impl, wc);
+ r.GenerateCandidates(Impl, subregion);
}
- AddBarrierDivergenceCandidates(LocalVars, Impl, wc);
-
- verifier.RaceInstrumenter.AddRaceCheckingCandidateInvariants(Impl, wc);
+ AddBarrierDivergenceCandidates(LocalVars, Impl, subregion);
- AddUserSuppliedInvariants(wc, UserSuppliedInvariants, Impl);
-
- AddCandidateInvariants(wc.Body, LocalVars, UserSuppliedInvariants, Impl);
- }
- else if (bb.ec is IfCmd)
- {
- IfCmd ifCmd = bb.ec as IfCmd;
- AddCandidateInvariants(ifCmd.thn, LocalVars, UserSuppliedInvariants, Impl);
- if (ifCmd.elseBlock != null)
- {
- AddCandidateInvariants(ifCmd.elseBlock, LocalVars, UserSuppliedInvariants, Impl);
- }
+ verifier.RaceInstrumenter.AddRaceCheckingCandidateInvariants(Impl, subregion);
- }
- else
- {
- Debug.Assert(bb.ec == null);
+ AddUserSuppliedInvariants(subregion, UserSuppliedInvariants, Impl);
}
}
- private void AddUserSuppliedInvariants(WhileCmd wc, List<Expr> UserSuppliedInvariants, Implementation Impl)
+ private void AddUserSuppliedInvariants(IRegion region, List<Expr> UserSuppliedInvariants, Implementation Impl)
{
foreach (Expr e in UserSuppliedInvariants)
{
+ /*
wc.Invariants.Add(new AssertCmd(wc.tok, e));
bool OK = verifier.ProgramIsOK(Impl);
wc.Invariants.RemoveAt(wc.Invariants.Count - 1);
@@ -197,30 +175,16 @@ namespace GPUVerify {
verifier.AddCandidateInvariant(wc, e, "user supplied");
}
+ */
+ verifier.AddCandidateInvariant(region, e, "user supplied");
}
}
- internal static HashSet<Variable> GetModifiedVariables(StmtList stmtList)
- {
- HashSet<Variable> result = new HashSet<Variable>();
-
- foreach (BigBlock bb in stmtList.BigBlocks)
- {
- HashSet<Variable> resultForBlock = GetModifiedVariables(bb);
- foreach (Variable v in resultForBlock)
- {
- result.Add(v);
- }
- }
-
- return result;
- }
-
- private static HashSet<Variable> GetModifiedVariables(BigBlock bb)
+ internal static HashSet<Variable> GetModifiedVariables(IRegion region)
{
HashSet<Variable> result = new HashSet<Variable>();
- foreach (Cmd c in bb.simpleCmds)
+ foreach (Cmd c in region.Cmds())
{
VariableSeq vars = new VariableSeq();
c.AddAssignedVariables(vars);
@@ -230,34 +194,6 @@ namespace GPUVerify }
}
- if (bb.ec is WhileCmd)
- {
- HashSet<Variable> modifiedByLoop = GetModifiedVariables((bb.ec as WhileCmd).Body);
- foreach (Variable v in modifiedByLoop)
- {
- result.Add(v);
- }
- }
- else if (bb.ec is IfCmd)
- {
- HashSet<Variable> modifiedByThen = GetModifiedVariables((bb.ec as IfCmd).thn);
- foreach (Variable v in modifiedByThen)
- {
- result.Add(v);
- }
-
- if ((bb.ec as IfCmd).elseBlock != null)
- {
- HashSet<Variable> modifiedByElse = GetModifiedVariables((bb.ec as IfCmd).elseBlock);
- foreach (Variable v in modifiedByElse)
- {
- result.Add(v);
- }
- }
-
- Debug.Assert((bb.ec as IfCmd).elseIf == null);
- }
-
return result;
}
diff --git a/Source/GPUVerify/Main.cs b/Source/GPUVerify/Main.cs index c8d29282..d1fcca9e 100644 --- a/Source/GPUVerify/Main.cs +++ b/Source/GPUVerify/Main.cs @@ -129,6 +129,12 @@ namespace GPUVerify {
fn = CommandLineOptions.outputFile;
}
+ else if (CommandLineOptions.inputFiles.Count == 1)
+ {
+ var inputFile = CommandLineOptions.inputFiles[0];
+ if (Path.GetExtension(inputFile).ToLower() != ".bpl")
+ fn = Path.GetFileNameWithoutExtension(inputFile);
+ }
ResolutionContext rc;
Program program = parse(out rc);
IList<GPUVerifier> result = new List<GPUVerifier>();
diff --git a/Source/GPUVerify/MayBeFlattened2DTidOrGidAnalyser.cs b/Source/GPUVerify/MayBeFlattened2DTidOrGidAnalyser.cs deleted file mode 100644 index 3d65ec61..00000000 --- a/Source/GPUVerify/MayBeFlattened2DTidOrGidAnalyser.cs +++ /dev/null @@ -1,347 +0,0 @@ -using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Diagnostics;
-using Microsoft.Boogie;
-
-namespace GPUVerify
-{
- class MayBeFlattened2DTidOrGidAnalyser
- {
- private static string[] cases = { "local", "global" };
-
- private GPUVerifier verifier;
-
- private bool ProcedureChanged;
-
- private Dictionary<string, Dictionary<string, Dictionary<string, bool>>> mayBeInfo;
-
- public MayBeFlattened2DTidOrGidAnalyser(GPUVerifier verifier)
- {
- this.verifier = verifier;
-
- mayBeInfo = new Dictionary<string,Dictionary<string,Dictionary<string,bool>>>();
- foreach (string s in cases)
- {
- mayBeInfo[s] = new Dictionary<string, Dictionary<string, bool>>();
- }
-
- }
-
- internal void Analyse()
- {
- foreach (Declaration D in verifier.Program.TopLevelDeclarations)
- {
- if(D is Implementation)
- {
- Implementation Impl = D as Implementation;
-
- foreach (string s in cases)
- {
- mayBeInfo[s][Impl.Name] = new Dictionary<string, bool>();
- }
-
- foreach (Variable v in Impl.LocVars)
- {
- foreach (string s in cases)
- {
- SetMayBe(s, Impl.Name, v.Name);
- }
- }
-
- foreach (Variable v in Impl.InParams)
- {
- foreach (string s in cases)
- {
- SetMayBe(s, Impl.Name, v.Name);
- }
- }
-
- foreach (Variable v in Impl.OutParams)
- {
- foreach (string s in cases)
- {
- SetMayBe(s, Impl.Name, v.Name);
- }
- }
-
- ProcedureChanged = true;
- }
- }
-
- while (ProcedureChanged)
- {
- ProcedureChanged = false;
-
- foreach (Declaration D in verifier.Program.TopLevelDeclarations)
- {
- if (D is Implementation)
- {
- Implementation Impl = D as Implementation;
- Analyse(Impl);
- }
- }
- }
-
- if (CommandLineOptions.ShowMayBeThreadConfigurationVariableAnalysis)
- {
- dump();
- }
- }
-
- private void Analyse(Implementation Impl)
- {
- Analyse(Impl, Impl.StructuredStmts);
- }
-
- private void Analyse(Implementation impl, StmtList stmtList)
- {
- foreach (BigBlock bb in stmtList.BigBlocks)
- {
- Analyse(impl, bb);
- }
- }
-
- private void Analyse(Implementation impl, BigBlock bb)
- {
- foreach (Cmd c in bb.simpleCmds)
- {
- if (c is AssignCmd)
- {
- foreach (string s in cases)
- {
- TransferAssign(impl, c as AssignCmd, s);
- }
- }
- else if (c is CallCmd)
- {
- foreach (string s in cases)
- {
- TransferCall(impl, c as CallCmd, s);
- }
- }
- else if (c is HavocCmd)
- {
- foreach (string s in cases)
- {
- TransferHavoc(impl, c as HavocCmd, s);
- }
- }
- }
-
- if (bb.ec is WhileCmd)
- {
- WhileCmd wc = bb.ec as WhileCmd;
- Analyse(impl, wc.Body);
- }
- else if (bb.ec is IfCmd)
- {
- IfCmd ifCmd = bb.ec as IfCmd;
- Analyse(impl, ifCmd.thn);
- if (ifCmd.elseBlock != null)
- {
- Analyse(impl, ifCmd.elseBlock);
- }
- Debug.Assert(ifCmd.elseIf == null);
- }
-
- }
-
- private void TransferHavoc(Implementation impl, HavocCmd havoc, string component)
- {
- Debug.Assert(havoc.Vars.Length == 1);
- if (MayBe(component, impl.Name, havoc.Vars[0].Decl.Name))
- {
- SetNot(component, impl.Name, havoc.Vars[0].Decl.Name);
- }
- }
-
- private void TransferCall(Implementation impl, CallCmd callCmd, string component)
- {
- if (callCmd.callee != verifier.BarrierProcedure.Name)
- {
-
- Implementation CalleeImplementation = verifier.GetImplementation(callCmd.callee);
- for (int i = 0; i < CalleeImplementation.InParams.Length; i++)
- {
- if (MayBe(component, callCmd.callee, CalleeImplementation.InParams[i].Name)
- && !MayBe(component, impl.Name, callCmd.Ins[i]))
- {
- SetNot(component, callCmd.callee, CalleeImplementation.InParams[i].Name);
- }
- }
-
- for (int i = 0; i < CalleeImplementation.OutParams.Length; i++)
- {
- if (MayBe(component, impl.Name, callCmd.Outs[i].Name)
- && !MayBe(component, callCmd.callee, CalleeImplementation.OutParams[i].Name))
- {
- SetNot(component, impl.Name, callCmd.Outs[i].Name);
- }
- }
-
- }
- }
-
- private void TransferAssign(Implementation impl, AssignCmd assignCmd, string component)
- {
- for (int i = 0; i != assignCmd.Lhss.Count; ++i)
- {
- if (assignCmd.Lhss[i] is SimpleAssignLhs)
- {
- SimpleAssignLhs lhs = assignCmd.Lhss[i] as SimpleAssignLhs;
- Expr rhs = assignCmd.Rhss[i];
-
- if (MayBe(component, impl.Name, lhs.AssignedVariable.Name)
- && !MayBe(component, impl.Name, rhs))
- {
- SetNot(component, impl.Name, lhs.AssignedVariable.Name);
- }
- }
- }
- }
-
- private void SetNot(string component, string proc, string v)
- {
- mayBeInfo[component][proc][v] = false;
- ProcedureChanged = true;
- }
-
- private void SetMayBe(string component, string proc, string v)
- {
- mayBeInfo[component][proc][v] = true;
- }
-
- internal bool MayBe(string component, string proc, string v)
- {
- if (!mayBeInfo[component].ContainsKey(proc))
- {
- return false;
- }
-
- if (!mayBeInfo[component][proc].ContainsKey(v))
- {
- return false;
- }
-
- return mayBeInfo[component][proc][v];
- }
-
- internal bool MayBe(string component, string proc, Expr e)
- {
- if (e is IdentifierExpr)
- {
- return MayBe(component, proc, (e as IdentifierExpr).Decl.Name);
- }
-
- if (e is NAryExpr && (e as NAryExpr).Fun.FunctionName.Equals("BV32_ADD"))
- {
- NAryExpr nary = e as NAryExpr;
-
- if (component.Equals("local"))
- {
- if (verifier.mayBeTidAnalyser.MayBe(GPUVerifier.LOCAL_ID_X_STRING, proc, nary.Args[1]))
- {
- return IsLocalIdYTimesGroupSizeX(proc, nary.Args[0]);
- }
-
- if (verifier.mayBeTidAnalyser.MayBe(GPUVerifier.LOCAL_ID_X_STRING, proc, nary.Args[0]))
- {
- return IsLocalIdYTimesGroupSizeX(proc, nary.Args[1]);
- }
- }
- else
- {
- Debug.Assert(component.Equals("global"));
- if (verifier.mayBeGidAnalyser.MayBe("x", proc, nary.Args[1]))
- {
- return IsGlobalIdYTimesGlobalSizeX(proc, nary.Args[0]);
- }
-
- if (verifier.mayBeGidAnalyser.MayBe("x", proc, nary.Args[0]))
- {
- return IsGlobalIdYTimesGlobalSizeX(proc, nary.Args[1]);
- }
- }
- }
-
- return false;
- }
-
- private bool IsLocalIdYTimesGroupSizeX(string proc, Expr expr)
- {
- if (expr is NAryExpr && (expr as NAryExpr).Fun.FunctionName.Equals("BV32_MUL"))
- {
- NAryExpr innerNary = expr as NAryExpr;
-
- if (IsLocalIdYAndGroupSizeX(proc, innerNary.Args[0], innerNary.Args[1]))
- {
- return true;
- }
-
- if (IsLocalIdYAndGroupSizeX(proc, innerNary.Args[1], innerNary.Args[0]))
- {
- return true;
- }
- }
- return false;
- }
-
- private bool IsLocalIdYAndGroupSizeX(string proc, Expr maybeLocalIdY, Expr maybeGroupSizeX)
- {
- return verifier.mayBeTidAnalyser.MayBe(GPUVerifier.LOCAL_ID_Y_STRING, proc, maybeLocalIdY) &&
- verifier.mayBeTidAnalyser.MayBe(GPUVerifier.GROUP_SIZE_X_STRING, proc, maybeGroupSizeX);
- }
-
-
- private bool IsGlobalIdYTimesGlobalSizeX(string proc, Expr expr)
- {
- if (expr is NAryExpr && (expr as NAryExpr).Fun.FunctionName.Equals("BV32_MUL"))
- {
- NAryExpr innerNary = expr as NAryExpr;
-
- if (IsGlobalIdYAndGlobalSizeX(proc, innerNary.Args[0], innerNary.Args[1]))
- {
- return true;
- }
-
- if (IsGlobalIdYAndGlobalSizeX(proc, innerNary.Args[1], innerNary.Args[0]))
- {
- return true;
- }
- }
- return false;
- }
-
- private bool IsGlobalIdYAndGlobalSizeX(string proc, Expr maybeGlobalIdY, Expr maybeGlobalSizeX)
- {
- return verifier.mayBeGidAnalyser.MayBe("y", proc, maybeGlobalIdY) &&
- verifier.mayBeGlobalSizeAnalyser.MayBe("x", proc, maybeGlobalSizeX);
- }
-
-
- private void dump()
- {
- foreach (string s in cases)
- {
- Console.WriteLine("*** flattened " + s + " id ***");
-
- foreach (string p in mayBeInfo[s].Keys)
- {
- Console.WriteLine(" Procedure " + p);
-
- foreach (string v in mayBeInfo[s][p].Keys)
- {
- if (mayBeInfo[s][p][v])
- {
- Console.WriteLine(" " + v + ": may be flattened " + s + " id");
- }
- }
- }
- }
-
- }
-
- }
-}
diff --git a/Source/GPUVerify/MayBeGidAnalyser.cs b/Source/GPUVerify/MayBeGidAnalyser.cs index 969e8935..f7d8c973 100644 --- a/Source/GPUVerify/MayBeGidAnalyser.cs +++ b/Source/GPUVerify/MayBeGidAnalyser.cs @@ -92,20 +92,12 @@ namespace GPUVerify private void Analyse(Implementation Impl)
{
- Analyse(Impl, Impl.StructuredStmts);
+ Analyse(Impl, verifier.RootRegion(Impl));
}
- private void Analyse(Implementation impl, StmtList stmtList)
+ private void Analyse(Implementation impl, IRegion region)
{
- foreach (BigBlock bb in stmtList.BigBlocks)
- {
- Analyse(impl, bb);
- }
- }
-
- private void Analyse(Implementation impl, BigBlock bb)
- {
- foreach (Cmd c in bb.simpleCmds)
+ foreach (Cmd c in region.Cmds())
{
if (c is AssignCmd)
{
@@ -129,23 +121,6 @@ namespace GPUVerify }
}
}
-
- if (bb.ec is WhileCmd)
- {
- WhileCmd wc = bb.ec as WhileCmd;
- Analyse(impl, wc.Body);
- }
- else if (bb.ec is IfCmd)
- {
- IfCmd ifCmd = bb.ec as IfCmd;
- Analyse(impl, ifCmd.thn);
- if (ifCmd.elseBlock != null)
- {
- Analyse(impl, ifCmd.elseBlock);
- }
- Debug.Assert(ifCmd.elseIf == null);
- }
-
}
private void TransferHavoc(Implementation impl, HavocCmd havoc, string component)
diff --git a/Source/GPUVerify/MayBeGlobalSizeAnalyser.cs b/Source/GPUVerify/MayBeGlobalSizeAnalyser.cs deleted file mode 100644 index 579f6805..00000000 --- a/Source/GPUVerify/MayBeGlobalSizeAnalyser.cs +++ /dev/null @@ -1,312 +0,0 @@ -using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Diagnostics;
-using Microsoft.Boogie;
-
-namespace GPUVerify
-{
- class MayBeGlobalSizeAnalyser
- {
- private static string[] dimensions = { "x", "y", "z" };
-
- private GPUVerifier verifier;
-
- private bool ProcedureChanged;
-
- private Dictionary<string, Dictionary<string, Dictionary<string, bool>>> mayBeInfo;
-
- public MayBeGlobalSizeAnalyser(GPUVerifier verifier)
- {
- this.verifier = verifier;
-
- mayBeInfo = new Dictionary<string,Dictionary<string,Dictionary<string,bool>>>();
- foreach (string s in dimensions)
- {
- mayBeInfo[s] = new Dictionary<string, Dictionary<string, bool>>();
- }
-
- }
-
- internal void Analyse()
- {
- foreach (Declaration D in verifier.Program.TopLevelDeclarations)
- {
- if(D is Implementation)
- {
- Implementation Impl = D as Implementation;
-
- foreach (string s in dimensions)
- {
- mayBeInfo[s][Impl.Name] = new Dictionary<string, bool>();
- }
-
- foreach (Variable v in Impl.LocVars)
- {
- foreach (string s in dimensions)
- {
- SetMayBe(s, Impl.Name, v.Name);
- }
- }
-
- foreach (Variable v in Impl.InParams)
- {
- foreach (string s in dimensions)
- {
- SetMayBe(s, Impl.Name, v.Name);
- }
- }
-
- foreach (Variable v in Impl.OutParams)
- {
- foreach (string s in dimensions)
- {
- SetMayBe(s, Impl.Name, v.Name);
- }
- }
-
- ProcedureChanged = true;
- }
- }
-
- while (ProcedureChanged)
- {
- ProcedureChanged = false;
-
- foreach (Declaration D in verifier.Program.TopLevelDeclarations)
- {
- if (D is Implementation)
- {
- Implementation Impl = D as Implementation;
- Analyse(Impl);
- }
- }
- }
-
- if (CommandLineOptions.ShowMayBeThreadConfigurationVariableAnalysis)
- {
- dump();
- }
- }
-
- private void Analyse(Implementation Impl)
- {
- Analyse(Impl, Impl.StructuredStmts);
- }
-
- private void Analyse(Implementation impl, StmtList stmtList)
- {
- foreach (BigBlock bb in stmtList.BigBlocks)
- {
- Analyse(impl, bb);
- }
- }
-
- private void Analyse(Implementation impl, BigBlock bb)
- {
- foreach (Cmd c in bb.simpleCmds)
- {
- if (c is AssignCmd)
- {
- foreach (string s in dimensions)
- {
- TransferAssign(impl, c as AssignCmd, s);
- }
- }
- else if (c is CallCmd)
- {
- foreach (string s in dimensions)
- {
- TransferCall(impl, c as CallCmd, s);
- }
- }
- else if (c is HavocCmd)
- {
- foreach (string s in dimensions)
- {
- TransferHavoc(impl, c as HavocCmd, s);
- }
- }
- }
-
- if (bb.ec is WhileCmd)
- {
- WhileCmd wc = bb.ec as WhileCmd;
- Analyse(impl, wc.Body);
- }
- else if (bb.ec is IfCmd)
- {
- IfCmd ifCmd = bb.ec as IfCmd;
- Analyse(impl, ifCmd.thn);
- if (ifCmd.elseBlock != null)
- {
- Analyse(impl, ifCmd.elseBlock);
- }
- Debug.Assert(ifCmd.elseIf == null);
- }
-
- }
-
- private void TransferHavoc(Implementation impl, HavocCmd havoc, string component)
- {
- Debug.Assert(havoc.Vars.Length == 1);
- if (MayBe(component, impl.Name, havoc.Vars[0].Decl.Name))
- {
- SetNot(component, impl.Name, havoc.Vars[0].Decl.Name);
- }
- }
-
- private void TransferCall(Implementation impl, CallCmd callCmd, string component)
- {
- if (callCmd.callee != verifier.BarrierProcedure.Name)
- {
-
- Implementation CalleeImplementation = verifier.GetImplementation(callCmd.callee);
- for (int i = 0; i < CalleeImplementation.InParams.Length; i++)
- {
- if (MayBe(component, callCmd.callee, CalleeImplementation.InParams[i].Name)
- && !MayBe(component, impl.Name, callCmd.Ins[i]))
- {
- SetNot(component, callCmd.callee, CalleeImplementation.InParams[i].Name);
- }
- }
-
- for (int i = 0; i < CalleeImplementation.OutParams.Length; i++)
- {
- if (MayBe(component, impl.Name, callCmd.Outs[i].Name)
- && !MayBe(component, callCmd.callee, CalleeImplementation.OutParams[i].Name))
- {
- SetNot(component, impl.Name, callCmd.Outs[i].Name);
- }
- }
-
- }
- }
-
- private void TransferAssign(Implementation impl, AssignCmd assignCmd, string component)
- {
- for (int i = 0; i != assignCmd.Lhss.Count; ++i)
- {
- if (assignCmd.Lhss[i] is SimpleAssignLhs)
- {
- SimpleAssignLhs lhs = assignCmd.Lhss[i] as SimpleAssignLhs;
- Expr rhs = assignCmd.Rhss[i];
-
- if (MayBe(component, impl.Name, lhs.AssignedVariable.Name)
- && !MayBe(component, impl.Name, rhs))
- {
- SetNot(component, impl.Name, lhs.AssignedVariable.Name);
- }
- }
- }
- }
-
- private void SetNot(string component, string proc, string v)
- {
- mayBeInfo[component][proc][v] = false;
- ProcedureChanged = true;
- }
-
- private void SetMayBe(string component, string proc, string v)
- {
- mayBeInfo[component][proc][v] = true;
- }
-
- internal bool MayBe(string component, string proc, string v)
- {
- if (!mayBeInfo[component].ContainsKey(proc))
- {
- return false;
- }
-
- if (!mayBeInfo[component][proc].ContainsKey(v))
- {
- return false;
- }
-
- return mayBeInfo[component][proc][v];
- }
-
- internal bool MayBe(string component, string proc, Expr e)
- {
- if (e is IdentifierExpr)
- {
- return MayBe(component, proc, (e as IdentifierExpr).Decl.Name);
- }
-
- return IsNumGroupsTimesGroupSize(component, proc, e);
-
- }
-
- private bool IsNumGroupsTimesGroupSize(string component, string proc, Expr expr)
- {
- if (expr is NAryExpr && (expr as NAryExpr).Fun.FunctionName.Equals("BV32_MUL"))
- {
- NAryExpr innerNary = expr as NAryExpr;
-
- if (IsNumGroupsAndGroupSize(component, proc, innerNary.Args[0], innerNary.Args[1]))
- {
- return true;
- }
-
- if (IsNumGroupsAndGroupSize(component, proc, innerNary.Args[1], innerNary.Args[0]))
- {
- return true;
- }
- }
- return false;
- }
-
- private bool IsNumGroupsAndGroupSize(string component, string proc, Expr maybeNumGroups, Expr maybeGroupSize)
- {
- string numGroupsString = null;
- string groupSizeString = null;
- if (component.Equals("x"))
- {
- numGroupsString = GPUVerifier.NUM_GROUPS_X_STRING;
- groupSizeString = GPUVerifier.GROUP_SIZE_X_STRING;
- }
- else if (component.Equals("y"))
- {
- numGroupsString = GPUVerifier.NUM_GROUPS_Y_STRING;
- groupSizeString = GPUVerifier.GROUP_SIZE_Y_STRING;
- }
- else if (component.Equals("z"))
- {
- numGroupsString = GPUVerifier.NUM_GROUPS_Z_STRING;
- groupSizeString = GPUVerifier.GROUP_SIZE_Z_STRING;
- }
- else
- {
- Debug.Assert(false);
- }
-
- return verifier.mayBeTidAnalyser.MayBe(numGroupsString, proc, maybeNumGroups) &&
- verifier.mayBeTidAnalyser.MayBe(groupSizeString, proc, maybeGroupSize);
- }
-
- private void dump()
- {
- foreach (string s in dimensions)
- {
- Console.WriteLine("*** global_size_" + s + " ***");
-
- foreach (string p in mayBeInfo[s].Keys)
- {
- Console.WriteLine(" Procedure " + p);
-
- foreach (string v in mayBeInfo[s][p].Keys)
- {
- if (mayBeInfo[s][p][v])
- {
- Console.WriteLine(" " + v + ": may be global_size_" + s);
- }
- }
- }
- }
-
- }
-
- }
-}
diff --git a/Source/GPUVerify/MayBeIdPlusConstantAnalyser.cs b/Source/GPUVerify/MayBeIdPlusConstantAnalyser.cs index a8563dfa..a57f35ee 100644 --- a/Source/GPUVerify/MayBeIdPlusConstantAnalyser.cs +++ b/Source/GPUVerify/MayBeIdPlusConstantAnalyser.cs @@ -79,21 +79,12 @@ namespace GPUVerify private void Analyse(Implementation Impl)
{
- Analyse(Impl, Impl.StructuredStmts);
+ Analyse(Impl, verifier.RootRegion(Impl));
}
- private void Analyse(Implementation impl, StmtList stmtList)
+ private void Analyse(Implementation impl, IRegion region)
{
- foreach (BigBlock bb in stmtList.BigBlocks)
- {
- Analyse(impl, bb);
- }
- }
-
-
- private void Analyse(Implementation impl, BigBlock bb)
- {
- foreach (Cmd c in bb.simpleCmds)
+ foreach (Cmd c in region.Cmds())
{
if (c is AssignCmd)
{
@@ -135,23 +126,6 @@ namespace GPUVerify }
}
}
-
- if (bb.ec is WhileCmd)
- {
- WhileCmd wc = bb.ec as WhileCmd;
- Analyse(impl, wc.Body);
- }
- else if (bb.ec is IfCmd)
- {
- IfCmd ifCmd = bb.ec as IfCmd;
- Analyse(impl, ifCmd.thn);
- if (ifCmd.elseBlock != null)
- {
- Analyse(impl, ifCmd.elseBlock);
- }
- Debug.Assert(ifCmd.elseIf == null);
- }
-
}
private string ConvertToString(Expr constantIncrement)
diff --git a/Source/GPUVerify/MayBePowerOfTwoAnalyser.cs b/Source/GPUVerify/MayBePowerOfTwoAnalyser.cs index 506add7c..c0f00dda 100644 --- a/Source/GPUVerify/MayBePowerOfTwoAnalyser.cs +++ b/Source/GPUVerify/MayBePowerOfTwoAnalyser.cs @@ -67,20 +67,12 @@ namespace GPUVerify private void Analyse(Implementation Impl)
{
- Analyse(Impl, Impl.StructuredStmts);
+ Analyse(Impl, verifier.RootRegion(Impl));
}
- private void Analyse(Implementation impl, StmtList stmtList)
+ private void Analyse(Implementation impl, IRegion region)
{
- foreach (BigBlock bb in stmtList.BigBlocks)
- {
- Analyse(impl, bb);
- }
- }
-
- private void Analyse(Implementation impl, BigBlock bb)
- {
- foreach (Cmd c in bb.simpleCmds)
+ foreach (Cmd c in region.Cmds())
{
if (c is AssignCmd)
{
@@ -102,23 +94,6 @@ namespace GPUVerify }
}
}
-
- if (bb.ec is WhileCmd)
- {
- WhileCmd wc = bb.ec as WhileCmd;
- Analyse(impl, wc.Body);
- }
- else if (bb.ec is IfCmd)
- {
- IfCmd ifCmd = bb.ec as IfCmd;
- Analyse(impl, ifCmd.thn);
- if (ifCmd.elseBlock != null)
- {
- Analyse(impl, ifCmd.elseBlock);
- }
- Debug.Assert(ifCmd.elseIf == null);
- }
-
}
private bool isPowerOfTwoOperation(Variable v, Expr expr)
diff --git a/Source/GPUVerify/MayBeThreadConfigurationVariableAnalyser.cs b/Source/GPUVerify/MayBeThreadConfigurationVariableAnalyser.cs index 53efbea8..d445d422 100644 --- a/Source/GPUVerify/MayBeThreadConfigurationVariableAnalyser.cs +++ b/Source/GPUVerify/MayBeThreadConfigurationVariableAnalyser.cs @@ -127,20 +127,12 @@ namespace GPUVerify private void Analyse(Implementation Impl)
{
- Analyse(Impl, Impl.StructuredStmts);
+ Analyse(Impl, verifier.RootRegion(Impl));
}
- private void Analyse(Implementation impl, StmtList stmtList)
+ private void Analyse(Implementation impl, IRegion region)
{
- foreach (BigBlock bb in stmtList.BigBlocks)
- {
- Analyse(impl, bb);
- }
- }
-
- private void Analyse(Implementation impl, BigBlock bb)
- {
- foreach (Cmd c in bb.simpleCmds)
+ foreach (Cmd c in region.Cmds())
{
if (c is AssignCmd)
{
@@ -164,23 +156,6 @@ namespace GPUVerify }
}
}
-
- if (bb.ec is WhileCmd)
- {
- WhileCmd wc = bb.ec as WhileCmd;
- Analyse(impl, wc.Body);
- }
- else if (bb.ec is IfCmd)
- {
- IfCmd ifCmd = bb.ec as IfCmd;
- Analyse(impl, ifCmd.thn);
- if (ifCmd.elseBlock != null)
- {
- Analyse(impl, ifCmd.elseBlock);
- }
- Debug.Assert(ifCmd.elseIf == null);
- }
-
}
private void TransferHavoc(Implementation impl, HavocCmd havoc, string component)
diff --git a/Source/GPUVerify/NullRaceInstrumenter.cs b/Source/GPUVerify/NullRaceInstrumenter.cs index 73f038fb..acba7ca6 100644 --- a/Source/GPUVerify/NullRaceInstrumenter.cs +++ b/Source/GPUVerify/NullRaceInstrumenter.cs @@ -9,7 +9,7 @@ namespace GPUVerify class NullRaceInstrumenter : IRaceInstrumenter
{
- public void AddRaceCheckingCandidateInvariants(Implementation impl, Microsoft.Boogie.WhileCmd wc)
+ public void AddRaceCheckingCandidateInvariants(Implementation impl, IRegion region)
{
}
@@ -24,9 +24,9 @@ namespace GPUVerify return true;
}
- public Microsoft.Boogie.BigBlock MakeResetReadWriteSetsStatements(Microsoft.Boogie.IToken tok)
+ public Microsoft.Boogie.BigBlock MakeResetReadWriteSetStatements(Variable v, int Thread)
{
- return new BigBlock(tok, "__ResetReadWriteSets", new CmdSeq(), null, null);
+ return new BigBlock(Token.NoToken, null, new CmdSeq(), null, null);
}
public void AddRaceCheckingCandidateRequires(Procedure Proc)
diff --git a/Source/GPUVerify/RaceInstrumenterBase.cs b/Source/GPUVerify/RaceInstrumenterBase.cs index a0c4b5f7..5155b192 100644 --- a/Source/GPUVerify/RaceInstrumenterBase.cs +++ b/Source/GPUVerify/RaceInstrumenterBase.cs @@ -48,7 +48,7 @@ namespace GPUVerify protected abstract void AddRequiresNoPendingAccess(Variable v);
- private void AddNoReadOrWriteCandidateInvariants(WhileCmd wc, Variable v)
+ private void AddNoReadOrWriteCandidateInvariants(IRegion region, Variable v)
{
// Reasoning: if READ_HAS_OCCURRED_v is not in the modifies set for the
// loop then there is no point adding an invariant
@@ -63,18 +63,18 @@ namespace GPUVerify //
// The same reasoning applies for WRITE
- if (verifier.ContainsBarrierCall(wc.Body))
+ if (verifier.ContainsBarrierCall(region))
{
if (verifier.ContainsNamedVariable(
- LoopInvariantGenerator.GetModifiedVariables(wc.Body), GPUVerifier.MakeAccessHasOccurredVariableName(v.Name, "READ")))
+ LoopInvariantGenerator.GetModifiedVariables(region), GPUVerifier.MakeAccessHasOccurredVariableName(v.Name, "READ")))
{
- AddNoReadOrWriteCandidateInvariant(wc, v, "READ");
+ AddNoReadOrWriteCandidateInvariant(region, v, "READ");
}
if (verifier.ContainsNamedVariable(
- LoopInvariantGenerator.GetModifiedVariables(wc.Body), GPUVerifier.MakeAccessHasOccurredVariableName(v.Name, "WRITE")))
+ LoopInvariantGenerator.GetModifiedVariables(region), GPUVerifier.MakeAccessHasOccurredVariableName(v.Name, "WRITE")))
{
- AddNoReadOrWriteCandidateInvariant(wc, v, "WRITE");
+ AddNoReadOrWriteCandidateInvariant(region, v, "WRITE");
}
}
}
@@ -91,47 +91,47 @@ namespace GPUVerify AddNoReadOrWriteCandidateEnsures(Proc, v, "WRITE", "1");
}
- private void AddNoReadOrWriteCandidateInvariant(WhileCmd wc, Variable v, string ReadOrWrite)
+ private void AddNoReadOrWriteCandidateInvariant(IRegion region, Variable v, string ReadOrWrite)
{
Expr candidate = NoReadOrWriteExpr(v, ReadOrWrite, "1");
- verifier.AddCandidateInvariant(wc, candidate, "no " + ReadOrWrite.ToLower());
+ verifier.AddCandidateInvariant(region, candidate, "no " + ReadOrWrite.ToLower());
}
- public void AddRaceCheckingCandidateInvariants(Implementation impl, WhileCmd wc)
+ public void AddRaceCheckingCandidateInvariants(Implementation impl, IRegion region)
{
foreach (Variable v in NonLocalStateToCheck.getAllNonLocalVariables())
{
- AddNoReadOrWriteCandidateInvariants(wc, v);
- AddReadOrWrittenOffsetIsThreadIdCandidateInvariants(impl, wc, v, "READ");
- AddReadOrWrittenOffsetIsThreadIdCandidateInvariants(impl, wc, v, "WRITE");
- AddGroupStrideAccessCandidateInvariants(impl, wc, v, "READ");
- AddGroupStrideAccessCandidateInvariants(impl, wc, v, "WRITE");
+ AddNoReadOrWriteCandidateInvariants(region, v);
+ AddReadOrWrittenOffsetIsThreadIdCandidateInvariants(impl, region, v, "READ");
+ AddReadOrWrittenOffsetIsThreadIdCandidateInvariants(impl, region, v, "WRITE");
+ AddGroupStrideAccessCandidateInvariants(impl, region, v, "READ");
+ AddGroupStrideAccessCandidateInvariants(impl, region, v, "WRITE");
}
}
- private void AddGroupStrideAccessCandidateInvariants(Implementation impl, WhileCmd wc, Variable v, string accessKind)
+ private void AddGroupStrideAccessCandidateInvariants(Implementation impl, IRegion region, Variable v, string accessKind)
{
- foreach (Expr e in GetOffsetsAccessed(wc.Body, v, accessKind))
+ foreach (Expr e in GetOffsetsAccessed(region, v, accessKind))
{
- if (TryGenerateCandidateForDirectStridedAccess(impl, wc, v, e, accessKind))
+ if (TryGenerateCandidateForDirectStridedAccess(impl, region, v, e, accessKind))
{
continue;
}
- if (!TryGenerateCandidateForReducedStrengthStrideVariable(impl, wc, v, e, accessKind))
+ if (!TryGenerateCandidateForReducedStrengthStrideVariable(impl, region, v, e, accessKind))
{
if (e is IdentifierExpr)
{
- foreach(Expr f in GetExpressionsFromWhichVariableIsAssignedInLoop(wc.Body, (e as IdentifierExpr).Decl))
+ foreach(Expr f in GetExpressionsFromWhichVariableIsAssignedInLoop(region, (e as IdentifierExpr).Decl))
{
- TryGenerateCandidateForReducedStrengthStrideVariable(impl, wc, v, f, accessKind);
+ TryGenerateCandidateForReducedStrengthStrideVariable(impl, region, v, f, accessKind);
}
}
}
}
}
- private bool TryGenerateCandidateForDirectStridedAccess(Implementation impl, WhileCmd wc, Variable v, Expr e, string accessKind)
+ private bool TryGenerateCandidateForDirectStridedAccess(Implementation impl, IRegion region, Variable v, Expr e, string accessKind)
{
if (!(e is NAryExpr))
{
@@ -157,7 +157,7 @@ namespace GPUVerify new IdentifierExpr(Token.NoToken, GPUVerifier.MakeAccessHasOccurredVariable(v.Name, accessKind)),
modPow2Expr);
- AddAccessRelatedCandidateInvariant(wc, accessKind, candidateInvariantExpr, impl.Name, "direct stride local");
+ AddAccessRelatedCandidateInvariant(region, accessKind, candidateInvariantExpr, impl.Name, "direct stride local");
return true;
}
}
@@ -173,7 +173,7 @@ namespace GPUVerify new IdentifierExpr(Token.NoToken, GPUVerifier.MakeAccessHasOccurredVariable(v.Name, accessKind)),
modPow2Expr);
- AddAccessRelatedCandidateInvariant(wc, accessKind, candidateInvariantExpr, impl.Name, "direct stride global");
+ AddAccessRelatedCandidateInvariant(region, accessKind, candidateInvariantExpr, impl.Name, "direct stride global");
return true;
}
}
@@ -182,10 +182,10 @@ namespace GPUVerify }
- private void AddAccessRelatedCandidateInvariant(WhileCmd wc, string accessKind, Expr candidateInvariantExpr, string procName, string tag)
+ private void AddAccessRelatedCandidateInvariant(IRegion region, string accessKind, Expr candidateInvariantExpr, string procName, string tag)
{
Expr candidate = new VariableDualiser(1, verifier.uniformityAnalyser, procName).VisitExpr(candidateInvariantExpr.Clone() as Expr);
- verifier.AddCandidateInvariant(wc, candidate, tag);
+ verifier.AddCandidateInvariant(region, candidate, tag);
}
private Expr IsIdPlusConstantMultiple(Expr arg1, Expr arg2, bool local, Implementation impl)
@@ -248,20 +248,20 @@ namespace GPUVerify return verifier.mayBeGidAnalyser.MayBe("x", impl.Name, mayBeId);
}
- private bool TryGenerateCandidateForReducedStrengthStrideVariable(Implementation impl, WhileCmd wc, Variable v, Expr e, string accessKind)
+ private bool TryGenerateCandidateForReducedStrengthStrideVariable(Implementation impl, IRegion region, Variable v, Expr e, string accessKind)
{
foreach (string w in
verifier.mayBeTidPlusConstantAnalyser.GetMayBeIdPlusConstantVars(impl.Name))
{
if (!verifier.ContainsNamedVariable(
- LoopInvariantGenerator.GetModifiedVariables(wc.Body), w))
+ LoopInvariantGenerator.GetModifiedVariables(region), w))
{
continue;
}
// Check also live
- if (GenerateModIdInvariants(impl, wc, v, e, accessKind, w, verifier.mayBeTidPlusConstantAnalyser))
+ if (GenerateModIdInvariants(impl, region, v, e, accessKind, w, verifier.mayBeTidPlusConstantAnalyser))
{
return true;
}
@@ -272,14 +272,14 @@ namespace GPUVerify verifier.mayBeGidPlusConstantAnalyser.GetMayBeIdPlusConstantVars(impl.Name))
{
if (!verifier.ContainsNamedVariable(
- LoopInvariantGenerator.GetModifiedVariables(wc.Body), w))
+ LoopInvariantGenerator.GetModifiedVariables(region), w))
{
continue;
}
// Check also live
- if (GenerateModIdInvariants(impl, wc, v, e, accessKind, w, verifier.mayBeGidPlusConstantAnalyser))
+ if (GenerateModIdInvariants(impl, region, v, e, accessKind, w, verifier.mayBeGidPlusConstantAnalyser))
{
return true;
}
@@ -290,7 +290,7 @@ namespace GPUVerify return false;
}
- private bool GenerateModIdInvariants(Implementation impl, WhileCmd wc, Variable v, Expr e, string accessKind,
+ private bool GenerateModIdInvariants(Implementation impl, IRegion region, Variable v, Expr e, string accessKind,
string w, MayBeIdPlusConstantAnalyser mayBeIdPlusConstantAnalyser)
{
if (!IsLinearFunctionOfVariable(e, w))
@@ -300,17 +300,17 @@ namespace GPUVerify Debug.Assert(!verifier.uniformityAnalyser.IsUniform(impl.Name, w));
- Variable wVariable = new LocalVariable(wc.tok, new TypedIdent(wc.tok, w,
+ Variable wVariable = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, w,
Microsoft.Boogie.Type.GetBvType(32)));
Expr indexModPow2EqualsId = ExprModPow2EqualsId(
- new IdentifierExpr(wc.tok, wVariable),
+ new IdentifierExpr(Token.NoToken, wVariable),
mayBeIdPlusConstantAnalyser.GetIncrement(impl.Name, w), mayBeIdPlusConstantAnalyser.MakeIdExpr());
- verifier.AddCandidateInvariant(wc,
+ verifier.AddCandidateInvariant(region,
new VariableDualiser(1, verifier.uniformityAnalyser, impl.Name).VisitExpr(indexModPow2EqualsId.Clone() as Expr),
"is " + mayBeIdPlusConstantAnalyser.idKind() + " plus constant multiple");
- verifier.AddCandidateInvariant(wc,
+ verifier.AddCandidateInvariant(region,
new VariableDualiser(2, verifier.uniformityAnalyser, impl.Name).VisitExpr(indexModPow2EqualsId.Clone() as Expr),
"is " + mayBeIdPlusConstantAnalyser.idKind() + " plus constant multiple");
@@ -325,29 +325,16 @@ namespace GPUVerify new IdentifierExpr(Token.NoToken, GPUVerifier.MakeAccessHasOccurredVariable(v.Name, accessKind)),
invertedOffsetModPow2EqualsId);
- AddAccessRelatedCandidateInvariant(wc, accessKind, candidateInvariantExpr, impl.Name, "accessed offset is "
+ AddAccessRelatedCandidateInvariant(region, accessKind, candidateInvariantExpr, impl.Name, "accessed offset is "
+ mayBeIdPlusConstantAnalyser.idKind() + " plus constant multiple");
return true;
}
- private HashSet<Expr> GetExpressionsFromWhichVariableIsAssignedInLoop(StmtList stmts, Variable variable)
+ private HashSet<Expr> GetExpressionsFromWhichVariableIsAssignedInLoop(IRegion region, Variable variable)
{
HashSet<Expr> result = new HashSet<Expr>();
- foreach (BigBlock bb in stmts.BigBlocks)
- {
- foreach (Expr e in GetExpressionsFromWhichVariableIsAssignedInLoop(bb, variable))
- {
- result.Add(e);
- }
- }
- return result;
- }
-
- private HashSet<Expr> GetExpressionsFromWhichVariableIsAssignedInLoop(BigBlock bb, Variable variable)
- {
- HashSet<Expr> result = new HashSet<Expr>();
- foreach (Cmd c in bb.simpleCmds)
+ foreach (Cmd c in region.Cmds())
{
if (c is AssignCmd)
{
@@ -370,34 +357,6 @@ namespace GPUVerify }
}
- if (bb.ec is WhileCmd)
- {
- foreach (Expr e in GetExpressionsFromWhichVariableIsAssignedInLoop((bb.ec as WhileCmd).Body, variable))
- {
- result.Add(e);
- }
- }
- else if (bb.ec is IfCmd)
- {
- IfCmd ifCmd = bb.ec as IfCmd;
-
- foreach (Expr e in GetExpressionsFromWhichVariableIsAssignedInLoop(ifCmd.thn, variable))
- {
- result.Add(e);
- }
-
- Debug.Assert(ifCmd.elseIf == null);
-
- if (ifCmd.elseBlock != null)
- {
- foreach (Expr e in GetExpressionsFromWhichVariableIsAssignedInLoop(ifCmd.elseBlock, variable))
- {
- result.Add(e);
- }
- }
-
- }
-
return result;
}
@@ -491,66 +450,34 @@ namespace GPUVerify return !visitor.found;
}
- private void AddReadOrWrittenOffsetIsThreadIdCandidateInvariants(Implementation impl, WhileCmd wc, Variable v, string accessType)
+ private void AddReadOrWrittenOffsetIsThreadIdCandidateInvariants(Implementation impl, IRegion region, Variable v, string accessType)
{
+ var offsets = GetOffsetsAccessed(region, v, accessType)
+ .Select(ofs => verifier.varDefAnalyses[impl].SubstDualisedDefinitions(ofs, 1, impl.Name))
+ .ToList();
- foreach (Expr e in GetOffsetsAccessed(wc.Body, v, accessType))
- {
- if (verifier.mayBeTidAnalyser.MayBe(GPUVerifier.LOCAL_ID_X_STRING, impl.Name, GPUVerifier.StripThreadIdentifiers(e)))
- {
- AddAccessedOffsetIsThreadLocalIdCandidateInvariant(wc, v, accessType);
- // No point adding it multiple times
- break;
- }
- }
-
- foreach (Expr e in GetOffsetsAccessed(wc.Body, v, accessType))
- {
- if (verifier.mayBeGidAnalyser.MayBe("x", impl.Name, GPUVerifier.StripThreadIdentifiers(e)))
- {
- AddAccessedOffsetIsThreadGlobalIdCandidateInvariant(wc, v, accessType);
- // No point adding it multiple times
- break;
- }
- }
-
- foreach (Expr e in GetOffsetsAccessed(wc.Body, v, accessType))
- {
- if (verifier.mayBeFlattened2DTidOrGidAnalyser.MayBe("local", impl.Name, GPUVerifier.StripThreadIdentifiers(e)))
- {
- AddAccessedOffsetIsThreadFlattened2DLocalIdCandidateInvariant(wc, v, accessType);
- // No point adding it multiple times
- break;
- }
- }
-
- foreach (Expr e in GetOffsetsAccessed(wc.Body, v, accessType))
+ if (!offsets.Contains(null))
{
- if (verifier.mayBeFlattened2DTidOrGidAnalyser.MayBe("global", impl.Name, GPUVerifier.StripThreadIdentifiers(e)))
- {
- AddAccessedOffsetIsThreadFlattened2DGlobalIdCandidateInvariant(wc, v, accessType);
- // No point adding it multiple times
- break;
- }
+ AddAccessedOffsetsAreConstantCandidateInvariant(region, v, offsets, accessType);
}
- KeyValuePair<IdentifierExpr, Expr> iLessThanC = GetILessThanC(wc.Guard);
+ KeyValuePair<IdentifierExpr, Expr> iLessThanC = GetILessThanC(region.Guard());
if (iLessThanC.Key != null)
{
- foreach (Expr e in GetOffsetsAccessed(wc.Body, v, accessType))
+ foreach (Expr e in GetOffsetsAccessed(region, v, accessType))
{
if(HasFormIPlusLocalIdTimesC(e, iLessThanC, impl))
{
- AddAccessedOffsetInRangeCTimesLocalIdToCTimesLocalIdPlusC(wc, v, iLessThanC.Value, accessType);
+ AddAccessedOffsetInRangeCTimesLocalIdToCTimesLocalIdPlusC(region, v, iLessThanC.Value, accessType);
break;
}
}
- foreach (Expr e in GetOffsetsAccessed(wc.Body, v, accessType))
+ foreach (Expr e in GetOffsetsAccessed(region, v, accessType))
{
if (HasFormIPlusGlobalIdTimesC(e, iLessThanC, impl))
{
- AddAccessedOffsetInRangeCTimesGlobalIdToCTimesGlobalIdPlusC(wc, v, iLessThanC.Value, accessType);
+ AddAccessedOffsetInRangeCTimesGlobalIdToCTimesGlobalIdPlusC(region, v, iLessThanC.Value, accessType);
break;
}
}
@@ -721,17 +648,11 @@ namespace GPUVerify AddAccessedOffsetIsThreadLocalIdCandidateEnsures(Proc, v, "READ", 1);
}
- protected abstract void AddAccessedOffsetIsThreadLocalIdCandidateInvariant(WhileCmd wc, Variable v, string ReadOrWrite);
-
- protected abstract void AddAccessedOffsetIsThreadGlobalIdCandidateInvariant(WhileCmd wc, Variable v, string ReadOrWrite);
+ protected abstract void AddAccessedOffsetInRangeCTimesLocalIdToCTimesLocalIdPlusC(IRegion region, Variable v, Expr constant, string ReadOrWrite);
- protected abstract void AddAccessedOffsetIsThreadFlattened2DLocalIdCandidateInvariant(WhileCmd wc, Variable v, string ReadOrWrite);
+ protected abstract void AddAccessedOffsetInRangeCTimesGlobalIdToCTimesGlobalIdPlusC(IRegion region, Variable v, Expr constant, string ReadOrWrite);
- protected abstract void AddAccessedOffsetIsThreadFlattened2DGlobalIdCandidateInvariant(WhileCmd wc, Variable v, string ReadOrWrite);
-
- protected abstract void AddAccessedOffsetInRangeCTimesLocalIdToCTimesLocalIdPlusC(WhileCmd wc, Variable v, Expr constant, string ReadOrWrite);
-
- protected abstract void AddAccessedOffsetInRangeCTimesGlobalIdToCTimesGlobalIdPlusC(WhileCmd wc, Variable v, Expr constant, string ReadOrWrite);
+ protected abstract void AddAccessedOffsetsAreConstantCandidateInvariant(IRegion region, Variable v, IEnumerable<Expr> offsets, string ReadOrWrite);
protected abstract void AddAccessedOffsetIsThreadLocalIdCandidateRequires(Procedure Proc, Variable v, string ReadOrWrite, int Thread);
@@ -877,7 +798,7 @@ namespace GPUVerify logAccessCallCmd.Proc = logProcedure;
- cs.Add(logAccessCallCmd);
+ result.Add(logAccessCallCmd);
}
}
@@ -914,7 +835,7 @@ namespace GPUVerify logAccessCallCmd.Proc = logProcedure;
- cs.Add(logAccessCallCmd);
+ result.Add(logAccessCallCmd);
addedLogWrite = true;
@@ -971,25 +892,30 @@ namespace GPUVerify protected abstract void AddLogAccessProcedure(Variable v, string ReadOrWrite);
- public BigBlock MakeResetReadWriteSetsStatements(IToken tok)
+ public BigBlock MakeResetReadWriteSetStatements(Variable v, int Thread)
{
- BigBlock result = new BigBlock(tok, "__ResetReadWriteSets", new CmdSeq(), null, null);
+ BigBlock result = new BigBlock(Token.NoToken, null, new CmdSeq(), null, null);
+ if (Thread == 2)
+ {
+ return result;
+ }
- foreach (Variable v in NonLocalStateToCheck.getAllNonLocalVariables())
+ Expr ResetReadAssumeGuard = Expr.Not(new IdentifierExpr(Token.NoToken,
+ new VariableDualiser(1, null, null).VisitVariable(GPUVerifier.MakeAccessHasOccurredVariable(v.Name, "READ"))));
+ Expr ResetWriteAssumeGuard = Expr.Not(new IdentifierExpr(Token.NoToken,
+ new VariableDualiser(1, null, null).VisitVariable(GPUVerifier.MakeAccessHasOccurredVariable(v.Name, "WRITE"))));
+
+ if (CommandLineOptions.InterGroupRaceChecking && verifier.NonLocalState.getGlobalVariables().Contains(v))
{
- SetNoAccessOccurred(tok, result, v);
+ ResetReadAssumeGuard = Expr.Imp(verifier.ThreadsInSameGroup(), ResetReadAssumeGuard);
+ ResetWriteAssumeGuard = Expr.Imp(verifier.ThreadsInSameGroup(), ResetWriteAssumeGuard);
}
- return result;
- }
- private void SetNoAccessOccurred(IToken tok, BigBlock bb, Variable v)
- {
- SetNoAccessOccurred(tok, bb, v, "READ");
- SetNoAccessOccurred(tok, bb, v, "WRITE");
+ result.simpleCmds.Add(new AssumeCmd(Token.NoToken, ResetReadAssumeGuard));
+ result.simpleCmds.Add(new AssumeCmd(Token.NoToken, ResetWriteAssumeGuard));
+ return result;
}
- protected abstract void SetNoAccessOccurred(IToken tok, BigBlock bb, Variable v, string AccessType);
-
protected Procedure MakeLogAccessProcedureHeader(Variable v, string ReadOrWrite)
{
VariableSeq inParams = new VariableSeq();
@@ -1049,24 +975,11 @@ namespace GPUVerify protected abstract Expr NoReadOrWriteExpr(Variable v, string ReadOrWrite, string OneOrTwo);
- private HashSet<Expr> GetOffsetsAccessed(StmtList stmts, Variable v, string AccessType)
- {
- HashSet<Expr> result = new HashSet<Expr> ();
- foreach (BigBlock bb in stmts.BigBlocks)
- {
- foreach (Expr e in GetOffsetsAccessed(bb, v, AccessType))
- {
- result.Add(e);
- }
- }
- return result;
- }
-
- private HashSet<Expr> GetOffsetsAccessed(BigBlock bb, Variable v, string AccessType)
+ private HashSet<Expr> GetOffsetsAccessed(IRegion region, Variable v, string AccessType)
{
HashSet<Expr> result = new HashSet<Expr>();
- foreach (Cmd c in bb.simpleCmds)
+ foreach (Cmd c in region.Cmds())
{
if (c is CallCmd)
{
@@ -1076,48 +989,27 @@ namespace GPUVerify {
// Ins[0] is thread 1's predicate,
// Ins[1] is the offset to be read
- // Ins[1] has the form BV32_ADD(offset#construct...(P), offset)
- // We are looking for the second parameter to this BV32_ADD
+ // If Ins[1] has the form BV32_ADD(offset#construct...(P), offset),
+ // we are looking for the second parameter to this BV32_ADD
Expr offset = call.Ins[1];
- Debug.Assert(offset is NAryExpr);
- Debug.Assert((offset as NAryExpr).Fun.FunctionName == "BV32_ADD");
- result.Add((offset as NAryExpr).Args[1]);
+ if (offset is NAryExpr)
+ {
+ var nExpr = (NAryExpr)offset;
+ if (nExpr.Fun.FunctionName == "BV32_ADD" &&
+ nExpr.Args[0] is NAryExpr)
+ {
+ var n0Expr = (NAryExpr)nExpr.Args[0];
+ if (n0Expr.Fun.FunctionName.StartsWith("offset#"))
+ offset = nExpr.Args[1];
+ }
+ }
+ result.Add(offset);
}
}
}
- if (bb.ec is WhileCmd)
- {
- HashSet<Expr> bodyResult = GetOffsetsAccessed((bb.ec as WhileCmd).Body, v, AccessType);
- foreach (Expr e in bodyResult)
- {
- result.Add(e);
- }
- }
- else if (bb.ec is IfCmd)
- {
- IfCmd ifCmd = bb.ec as IfCmd;
-
- HashSet<Expr> thenResult = GetOffsetsAccessed(ifCmd.thn, v, AccessType);
- foreach (Expr e in thenResult)
- {
- result.Add(e);
- }
-
- Debug.Assert(ifCmd.elseIf == null);
-
- if(ifCmd.elseBlock != null)
- {
- HashSet<Expr> elseResult = GetOffsetsAccessed(ifCmd.elseBlock, v, AccessType);
- foreach (Expr e in elseResult)
- {
- result.Add(e);
- }
- }
- }
-
return result;
}
diff --git a/Source/GPUVerify/StructuredRegion.cs b/Source/GPUVerify/StructuredRegion.cs new file mode 100644 index 00000000..366682e0 --- /dev/null +++ b/Source/GPUVerify/StructuredRegion.cs @@ -0,0 +1,121 @@ +using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Microsoft.Boogie;
+
+namespace GPUVerify {
+
+class StructuredRegion : IRegion {
+ Implementation impl;
+ WhileCmd cmd;
+
+ public StructuredRegion(Implementation impl) {
+ this.impl = impl;
+ }
+
+ public StructuredRegion(WhileCmd cmd) {
+ this.cmd = cmd;
+ }
+
+ public object Identifier() {
+ if (cmd != null)
+ return cmd;
+ else
+ return impl;
+ }
+
+ private StmtList StmtList() {
+ if (cmd != null)
+ return cmd.Body;
+ else
+ return impl.StructuredStmts;
+ }
+
+ private IEnumerable<Cmd> Cmds(StmtList stmts) {
+ foreach (var bb in stmts.BigBlocks) {
+ foreach (Cmd c in bb.simpleCmds)
+ yield return c;
+
+ if (bb.ec is IfCmd) {
+ var ic = (IfCmd)bb.ec;
+ foreach (var c in Cmds(ic.thn))
+ yield return c;
+
+ if (ic.elseBlock != null)
+ foreach (var c in Cmds(ic.elseBlock))
+ yield return c;
+ } else if (bb.ec is WhileCmd) {
+ var wc = (WhileCmd)bb.ec;
+ foreach (var c in Cmds(wc.Body))
+ yield return c;
+ }
+ }
+ }
+
+ private IEnumerable<object> CmdsChildRegions(StmtList stmts) {
+ foreach (var bb in stmts.BigBlocks) {
+ foreach (Cmd c in bb.simpleCmds)
+ yield return c;
+
+ if (bb.ec is IfCmd) {
+ var ic = (IfCmd)bb.ec;
+ foreach (var c in Cmds(ic.thn))
+ yield return c;
+
+ if (ic.elseBlock != null)
+ foreach (var c in Cmds(ic.elseBlock))
+ yield return c;
+ } else if (bb.ec is WhileCmd) {
+ var wc = (WhileCmd)bb.ec;
+ yield return new StructuredRegion(wc);
+ }
+ }
+ }
+
+ private IEnumerable<IRegion> SubRegions(StmtList stmts) {
+ foreach (var bb in stmts.BigBlocks) {
+ if (bb.ec is IfCmd) {
+ var ic = (IfCmd)bb.ec;
+ foreach (var r in SubRegions(ic.thn))
+ yield return r;
+
+ if (ic.elseBlock != null)
+ foreach (var r in SubRegions(ic.elseBlock))
+ yield return r;
+ } else if (bb.ec is WhileCmd) {
+ var wc = (WhileCmd)bb.ec;
+ yield return new StructuredRegion(wc);
+
+ foreach (var r in SubRegions(wc.Body))
+ yield return r;
+ }
+ }
+ }
+
+ public IEnumerable<Cmd> Cmds() {
+ return Cmds(StmtList());
+ }
+
+ public IEnumerable<object> CmdsChildRegions() {
+ return CmdsChildRegions(StmtList());
+ }
+
+ public IEnumerable<IRegion> SubRegions() {
+ return SubRegions(StmtList());
+ }
+
+ public Expr Guard() {
+ if (cmd != null)
+ return cmd.Guard;
+ else
+ return null;
+ }
+
+ public void AddInvariant(PredicateCmd pc) {
+ if (cmd != null)
+ cmd.Invariants.Add(pc);
+ }
+}
+
+}
diff --git a/Source/GPUVerify/UniformityAnalyser.cs b/Source/GPUVerify/UniformityAnalyser.cs index bd0e3f74..35f297ed 100644 --- a/Source/GPUVerify/UniformityAnalyser.cs +++ b/Source/GPUVerify/UniformityAnalyser.cs @@ -63,6 +63,10 @@ namespace GPUVerify SetNonUniform(Impl.Name, GPUVerifier._Y.Name);
SetNonUniform(Impl.Name, GPUVerifier._Z.Name);
+ SetNonUniform(Impl.Name, GPUVerifier._GROUP_X.Name);
+ SetNonUniform(Impl.Name, GPUVerifier._GROUP_Y.Name);
+ SetNonUniform(Impl.Name, GPUVerifier._GROUP_Z.Name);
+
foreach (Variable v in Impl.LocVars)
{
if (CommandLineOptions.DoUniformityAnalysis)
diff --git a/Source/GPUVerify/UnstructuredRegion.cs b/Source/GPUVerify/UnstructuredRegion.cs new file mode 100644 index 00000000..239f7ca0 --- /dev/null +++ b/Source/GPUVerify/UnstructuredRegion.cs @@ -0,0 +1,97 @@ +using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Microsoft.Boogie;
+using Graphing;
+
+namespace GPUVerify {
+
+class UnstructuredRegion : IRegion {
+ Graph<Block> blockGraph;
+ Block header;
+ Dictionary<Block, HashSet<Block>> loopNodes = new Dictionary<Block, HashSet<Block>>();
+ Dictionary<Block, Block> innermostHeader = new Dictionary<Block, Block>();
+ Expr guard;
+
+ public UnstructuredRegion(Program p, Implementation impl) {
+ blockGraph = p.ProcessLoops(impl);
+ header = null;
+ foreach (var h in blockGraph.SortHeadersByDominance()) {
+ var loopNodes = new HashSet<Block>();
+ foreach (var b in blockGraph.BackEdgeNodes(h))
+ loopNodes.UnionWith(blockGraph.NaturalLoops(h, b));
+ this.loopNodes[h] = loopNodes;
+ foreach (var n in loopNodes)
+ if (n != h)
+ innermostHeader[n] = h;
+ }
+ guard = null;
+ }
+
+ private UnstructuredRegion(UnstructuredRegion r, Block h) {
+ blockGraph = r.blockGraph;
+ header = h;
+ loopNodes = r.loopNodes;
+ innermostHeader = r.innermostHeader;
+ guard = null;
+ }
+
+ public object Identifier() {
+ return header;
+ }
+
+ private HashSet<Block> SubBlocks() {
+ if (header != null) {
+ return loopNodes[header];
+ } else {
+ return blockGraph.Nodes;
+ }
+ }
+
+ public IEnumerable<Cmd> Cmds() {
+ foreach (var b in SubBlocks())
+ foreach (Cmd c in b.Cmds)
+ yield return c;
+ }
+
+ public IEnumerable<object> CmdsChildRegions() {
+ foreach (var b in SubBlocks()) {
+ if (b == header)
+ foreach (Cmd c in b.Cmds)
+ yield return c;
+ else if (innermostHeader[b] == header) {
+ if (loopNodes.ContainsKey(b))
+ yield return new UnstructuredRegion(this, b);
+ else
+ foreach (Cmd c in b.Cmds)
+ yield return c;
+ }
+ }
+ }
+
+ public IEnumerable<IRegion> SubRegions() {
+ return SubBlocks().Intersect(loopNodes.Keys).Select(b => new UnstructuredRegion(this, b));
+ }
+
+ public Expr Guard() {
+ if (header == null)
+ return null;
+ if (guard == null) {
+ var backedges = blockGraph.BackEdgeNodes(header);
+ if (backedges.Count() != 1)
+ return null;
+ var assumes = backedges.Single().Cmds.Cast<Cmd>().OfType<AssumeCmd>();
+ if (assumes.Count() != 1)
+ return null;
+ guard = assumes.Single().Expr;
+ }
+ return guard;
+ }
+
+ public void AddInvariant(PredicateCmd pc) {
+ header.Cmds = new CmdSeq((new Cmd[] {pc}.Concat(header.Cmds.Cast<Cmd>())).ToArray());
+ }
+}
+
+}
diff --git a/Source/GPUVerify/VariableDefinitionAnalysis.cs b/Source/GPUVerify/VariableDefinitionAnalysis.cs new file mode 100644 index 00000000..f55e51e8 --- /dev/null +++ b/Source/GPUVerify/VariableDefinitionAnalysis.cs @@ -0,0 +1,155 @@ +using System;
+using Microsoft.Boogie;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace GPUVerify {
+
+class VariableDefinitionAnalysis {
+ GPUVerifier verifier;
+ Implementation impl;
+
+ Dictionary<Variable, Expr> defMap = new Dictionary<Variable, Expr>();
+ Dictionary<string, Expr> namedDefMap = new Dictionary<string, Expr>();
+ bool changed;
+
+ VariableDefinitionAnalysis(GPUVerifier v, Implementation i) {
+ verifier = v;
+ impl = i;
+ }
+
+ private class IsConstantVisitor : StandardVisitor {
+ private VariableDefinitionAnalysis analysis;
+ public bool isConstant = true;
+
+ public IsConstantVisitor(VariableDefinitionAnalysis a) {
+ analysis = a;
+ }
+
+ public override Expr VisitNAryExpr(NAryExpr expr) {
+ if (expr.Fun is MapSelect) {
+ isConstant = false;
+ return expr;
+ } else
+ return base.VisitNAryExpr(expr);
+ }
+
+ public override Expr VisitIdentifierExpr(IdentifierExpr expr) {
+ if (expr.Decl is Constant)
+ return expr;
+ if (!analysis.defMap.ContainsKey(expr.Decl) || analysis.defMap[expr.Decl] == null)
+ isConstant = false;
+ return expr;
+ }
+ };
+
+ bool IsConstant(Expr e) {
+ var v = new IsConstantVisitor(this);
+ v.Visit(e);
+ return v.isConstant;
+ }
+
+ void UpdateDefMap(Variable v, Expr def) {
+ if (!defMap.ContainsKey(v) || defMap[v] != def) {
+ changed = true;
+ defMap[v] = def;
+ }
+ }
+
+ void AddAssignment(AssignLhs lhs, Expr rhs) {
+ if (lhs is SimpleAssignLhs) {
+ var sLhs = (SimpleAssignLhs)lhs;
+ var theVar = sLhs.DeepAssignedVariable;
+ if ((defMap.ContainsKey(theVar) && defMap[theVar] != rhs) || !IsConstant(rhs)) {
+ UpdateDefMap(theVar, null);
+ } else {
+ UpdateDefMap(theVar, rhs);
+ }
+ }
+ }
+
+ void Analyse() {
+ do {
+ changed = false;
+ foreach (var c in verifier.RootRegion(impl).Cmds()) {
+ if (c is AssignCmd) {
+ var aCmd = (AssignCmd)c;
+ foreach (var a in aCmd.Lhss.Zip(aCmd.Rhss)) {
+ AddAssignment(a.Item1, a.Item2);
+ }
+ }
+ }
+ } while (changed);
+ }
+
+ private class BuildNamedDefVisitor : StandardVisitor {
+ private VariableDefinitionAnalysis analysis;
+
+ public BuildNamedDefVisitor(VariableDefinitionAnalysis a) {
+ analysis = a;
+ }
+
+ public override Expr VisitIdentifierExpr(IdentifierExpr expr) {
+ if (expr.Decl is Constant)
+ return expr;
+ return analysis.BuildNamedDefFor(expr.Decl);
+ }
+ }
+
+ Expr BuildNamedDefFor(Variable v) {
+ Expr def;
+ if (namedDefMap.TryGetValue(v.Name, out def))
+ return def;
+ def = (Expr)new BuildNamedDefVisitor(this).Visit(defMap[v].Clone());
+ namedDefMap[v.Name] = def;
+ return def;
+ }
+
+ void BuildNamedDefMap() {
+ foreach (var v in defMap.Keys)
+ if (defMap[v] != null)
+ BuildNamedDefFor(v);
+ }
+
+ private class SubstDualisedDefVisitor : StandardVisitor {
+ private VariableDefinitionAnalysis analysis;
+ private VariableDualiser dualiser;
+ public bool isSubstitutable = true;
+
+ public SubstDualisedDefVisitor(VariableDefinitionAnalysis a, int id, string procName) {
+ analysis = a;
+ dualiser = new VariableDualiser(id, analysis.verifier.uniformityAnalyser, procName);
+ }
+
+ public override Expr VisitIdentifierExpr(IdentifierExpr expr) {
+ if (expr.Decl is Constant)
+ return dualiser.VisitIdentifierExpr(expr);
+ var varName = GPUVerifier.StripThreadIdentifier(expr.Decl.Name);
+ Expr def;
+ if (!analysis.namedDefMap.TryGetValue(varName, out def)) {
+ isSubstitutable = false;
+ return null;
+ }
+ return (Expr)dualiser.Visit(def.Clone());
+ }
+ }
+
+ public Expr SubstDualisedDefinitions(Expr e, int id, string procName) {
+ var v = new SubstDualisedDefVisitor(this, id, procName);
+ Expr result = (Expr)v.Visit(e.Clone());
+ if (!v.isSubstitutable)
+ return null;
+ return result;
+ }
+
+ public static VariableDefinitionAnalysis Analyse(GPUVerifier verifier, Implementation impl) {
+ var a = new VariableDefinitionAnalysis(verifier, impl);
+ a.Analyse();
+ a.BuildNamedDefMap();
+ a.defMap = null;
+ return a;
+ }
+
+}
+
+}
diff --git a/Source/GPUVerify/VariableDualiser.cs b/Source/GPUVerify/VariableDualiser.cs index 7f637734..63720c13 100644 --- a/Source/GPUVerify/VariableDualiser.cs +++ b/Source/GPUVerify/VariableDualiser.cs @@ -36,6 +36,11 @@ namespace GPUVerify return new IdentifierExpr(node.tok, new Constant(node.tok, DualiseTypedIdent(node.Decl)));
}
+ if (CommandLineOptions.InterGroupRaceChecking && GPUVerifier.IsGroupIdConstant(node.Decl))
+ {
+ return new IdentifierExpr(node.tok, new Constant(node.tok, DualiseTypedIdent(node.Decl)));
+ }
+
return node;
}
@@ -52,7 +57,8 @@ namespace GPUVerify public override Variable VisitVariable(Variable node)
{
- if (!(node is Constant) || GPUVerifier.IsThreadLocalIdConstant(node))
+ if (!(node is Constant) || GPUVerifier.IsThreadLocalIdConstant(node) ||
+ (CommandLineOptions.InterGroupRaceChecking && GPUVerifier.IsGroupIdConstant(node)))
{
node.TypedIdent = DualiseTypedIdent(node);
node.Name = node.Name + "$" + id;
diff --git a/Source/Graph/Graph.cs b/Source/Graph/Graph.cs index e5e8444c..b5590865 100644 --- a/Source/Graph/Graph.cs +++ b/Source/Graph/Graph.cs @@ -843,6 +843,19 @@ namespace Graphing { }
return dag.TopologicalSort();
}
+
+ public string ToDot(Func<Node, string> NodeLabel = null, Func<Node, string> NodeStyle = null) {
+ NodeLabel = NodeLabel ?? (n => n.ToString());
+ NodeStyle = NodeStyle ?? (n => "[shape=box]");
+ var s = new StringBuilder();
+ s.AppendLine("digraph G {");
+ foreach (var n in Nodes)
+ s.AppendLine(" \"" + NodeLabel(n) + "\" " + NodeStyle(n) + ";");
+ foreach (var e in Edges)
+ s.AppendLine(" \"" + NodeLabel(e.Item1) + "\" -> \"" + NodeLabel(e.Item2) + "\";");
+ s.AppendLine("}");
+ return s.ToString();
+ }
} // end: class Graph
public class GraphProgram {
diff --git a/Source/Houdini/Houdini.cs b/Source/Houdini/Houdini.cs index d753762f..ab2fa74f 100644 --- a/Source/Houdini/Houdini.cs +++ b/Source/Houdini/Houdini.cs @@ -279,11 +279,6 @@ namespace Microsoft.Boogie.Houdini { }
}
- public class Macro : Function {
- public Macro(IToken tok, string name, VariableSeq args, Variable result)
- : base(tok, name, args, result) { }
- }
-
public class FreeRequiresVisitor : StandardVisitor {
public override Requires VisitRequires(Requires requires) {
if (requires.Free)
@@ -301,6 +296,13 @@ namespace Microsoft.Boogie.Houdini { }
}
+ public class InlineEnsuresVisitor : StandardVisitor {
+ public override Ensures VisitEnsures(Ensures ensures) {
+ ensures.Attributes = new QKeyValue(Token.NoToken, "assume", new List<object>(), ensures.Attributes);
+ return base.VisitEnsures(ensures);
+ }
+ }
+
public class Houdini : ObservableHoudini {
private Program program;
private HashSet<Variable> houdiniConstants;
@@ -367,6 +369,11 @@ namespace Microsoft.Boogie.Houdini { }
foreach (Implementation impl in callGraph.Nodes) {
+ InlineEnsuresVisitor inlineEnsuresVisitor = new InlineEnsuresVisitor();
+ inlineEnsuresVisitor.Visit(impl);
+ }
+
+ foreach (Implementation impl in callGraph.Nodes) {
impl.OriginalBlocks = impl.Blocks;
impl.OriginalLocVars = impl.LocVars;
}
diff --git a/Source/Model/Model.cs b/Source/Model/Model.cs index 204d130e..325ba03e 100644 --- a/Source/Model/Model.cs +++ b/Source/Model/Model.cs @@ -74,6 +74,14 @@ namespace Microsoft.Boogie }
public abstract ElementKind Kind { get; }
public virtual int AsInt() { throw new NotImplementedException(); }
+
+ public override int GetHashCode() {
+ return Id;
+ }
+
+ public override bool Equals(object obj) {
+ return obj == this;
+ }
}
#region element kinds
@@ -166,6 +174,17 @@ namespace Microsoft.Boogie return string.Format("{0}/{1}", Name, Arity);
}
+ internal void Substitute(Dictionary<Element, Element> mapping) {
+ Element e;
+ if (@else != null && mapping.TryGetValue(@else, out e))
+ @else = e;
+ foreach (var ft in apps) {
+ if (mapping.TryGetValue(ft.Result, out e)) ft.Result = e;
+ for (var i = 0; i < ft.Args.Length; ++i)
+ if (mapping.TryGetValue(ft.Args[i], out e)) ft.Args[i] = e;
+ }
+ }
+
public Element Else
{
get
@@ -322,7 +341,7 @@ namespace Microsoft.Boogie }
return null;
}
-
+
/// <summary>
/// Short for TryEval(args) == (Element)true
/// </summary>
@@ -366,8 +385,9 @@ namespace Microsoft.Boogie {
static readonly Element[] EmptyArgs = new Element[0];
+ // These should be immutable, except when Substituting the entire model
public readonly Func Func;
- public readonly Element Result;
+ public Element Result;
public readonly Element[] Args;
internal FuncTuple(Func func, Element res, Element[] args)
@@ -676,6 +696,10 @@ namespace Microsoft.Boogie wr.WriteLine("*** END_MODEL");
}
+ public void Substitute(Dictionary<Element, Element> mapping) {
+ foreach (var f in functions) f.Substitute(mapping);
+ }
+
class Parser
{
internal System.IO.TextReader rd;
@@ -799,6 +823,8 @@ namespace Microsoft.Boogie internal void Run()
{
+ var selectFunctions = new Dictionary<int, Model.Func>();
+ var storeFunctions = new Dictionary<int, Model.Func>();
for (; ; ) {
var line = ReadLine();
if (line == null) break; // end of model, everything fine
@@ -854,21 +880,38 @@ namespace Microsoft.Boogie if (fn == null)
fn = currModel.MkFunc(funName, 1);
if (tuple0 == "}") break;
- fn.Else = GetElt(tuple[0]);
+ if (fn.Else == null)
+ fn.Else = GetElt(tuple[0]);
continue;
}
string tuplePenultimate = tuple[tuple.Count - 2] as string;
if (tuplePenultimate != "->") BadModel("invalid function tuple definition");
var resultName = tuple[tuple.Count - 1];
if (tuple0 == "else") {
- if (fn != null && !(resultName is string && ((string)resultName) == "#unspecified")) {
+ if (fn != null && !(resultName is string && ((string)resultName) == "#unspecified") && fn.Else == null) {
fn.Else = GetElt(resultName);
}
continue;
}
- if (fn == null)
- fn = currModel.MkFunc(funName, tuple.Count - 2);
+ if (fn == null) {
+ var arity = tuple.Count - 2;
+ if (Regex.IsMatch(funName, "^MapType[0-9]*Select$")) {
+ funName = string.Format("[{0}]", arity);
+ if (!selectFunctions.TryGetValue(arity, out fn)) {
+ fn = currModel.MkFunc(funName, arity);
+ selectFunctions.Add(arity, fn);
+ }
+ } else if (Regex.IsMatch(funName, "^MapType[0-9]*Store$")) {
+ funName = string.Format("[{0}:=]", arity);
+ if (!storeFunctions.TryGetValue(arity, out fn)) {
+ fn = currModel.MkFunc(funName, arity);
+ storeFunctions.Add(arity, fn);
+ }
+ } else {
+ fn = currModel.MkFunc(funName, arity);
+ }
+ }
var args = new Element[fn.Arity];
for (int i = 0; i < fn.Arity; ++i)
args[i] = GetElt(tuple[i]);
diff --git a/Source/ModelViewer/DafnyProvider.cs b/Source/ModelViewer/DafnyProvider.cs index 328bbb26..6e4698d9 100644 --- a/Source/ModelViewer/DafnyProvider.cs +++ b/Source/ModelViewer/DafnyProvider.cs @@ -54,10 +54,10 @@ namespace Microsoft.Boogie.ModelViewer.Dafny // collect the array dimensions from the various array.Length functions, and
// collect all known datatype values
foreach (var fn in m.Functions) {
- if (Regex.IsMatch(fn.Name, "^array[0-9]*.Length[0-9]*$")) {
- int j = fn.Name.IndexOf('.', 5);
- int dims = j == 5 ? 1 : int.Parse(fn.Name.Substring(5, j - 5));
- int idx = j == 5 ? 0 : int.Parse(fn.Name.Substring(j + 7));
+ if (Regex.IsMatch(fn.Name, "^_System.array[0-9]*.Length[0-9]*$")) {
+ int j = fn.Name.IndexOf('.', 13);
+ int dims = j == 13 ? 1 : int.Parse(fn.Name.Substring(13, j - 13));
+ int idx = j == 13 ? 0 : int.Parse(fn.Name.Substring(j + 7));
foreach (var tpl in fn.Apps) {
var elt = tpl.Args[0];
var len = tpl.Result;
diff --git a/Source/Provers/SMTLib/ProverInterface.cs b/Source/Provers/SMTLib/ProverInterface.cs index 65c4e130..31afbdfa 100644 --- a/Source/Provers/SMTLib/ProverInterface.cs +++ b/Source/Provers/SMTLib/ProverInterface.cs @@ -770,12 +770,13 @@ namespace Microsoft.Boogie.SMTLib SendThisVC(a);
}
- public override void DefineMacro(Function fun, VCExpr vc) {
- DeclCollector.AddFunction(fun);
- string name = Namer.GetName(fun, fun.Name);
- string a = "(define-fun " + name + "() Bool " + VCExpr2String(vc, 1) + ")";
+ public override void DefineMacro(Macro f, VCExpr vc) {
+ DeclCollector.AddFunction(f);
+ string printedName = Namer.GetQuotedName(f, f.Name);
+ var argTypes = f.InParams.Cast<Variable>().MapConcat(p => DeclCollector.TypeToStringReg(p.TypedIdent.Type), " ");
+ string decl = "(define-fun " + printedName + " (" + argTypes + ") " + DeclCollector.TypeToStringReg(f.OutParams[0].TypedIdent.Type) + " " + VCExpr2String(vc, 1) + ")";
AssertAxioms();
- SendThisVC(a);
+ SendThisVC(decl);
}
public override void AssertAxioms()
diff --git a/Source/Provers/Z3api/ContextLayer.cs b/Source/Provers/Z3api/ContextLayer.cs index e0fddc63..df40df3d 100644 --- a/Source/Provers/Z3api/ContextLayer.cs +++ b/Source/Provers/Z3api/ContextLayer.cs @@ -20,6 +20,8 @@ namespace Microsoft.Boogie.Z3 { internal BacktrackDictionary<string, Term> constants = new BacktrackDictionary<string, Term>();
internal BacktrackDictionary<string, FuncDecl> functions = new BacktrackDictionary<string, FuncDecl>();
internal BacktrackDictionary<string, Term> labels = new BacktrackDictionary<string, Term>();
+ internal BacktrackDictionary<Term, VCExpr> constants_inv = null;
+ internal BacktrackDictionary<FuncDecl, Function> functions_inv = null;
public Config config;
public Context z3;
@@ -56,7 +58,13 @@ namespace Microsoft.Boogie.Z3 { z3 = new Context(config);
z3.SetPrintMode(PrintMode.Smtlib2Compliant);
if (logFilename != null)
- z3.OpenLog(logFilename);
+ {
+#if true
+ Z3Log.Open(logFilename);
+#else
+ z3.OpenLog(logFilename);
+#endif
+ }
foreach (string tag in debugTraces)
z3.EnableDebugTrace(tag);
@@ -65,6 +73,227 @@ namespace Microsoft.Boogie.Z3 { this.namer = new UniqueNamer();
}
+ public Z3apiProverContext(Context ctx, VCExpressionGenerator gen)
+ : base(gen, new VCGenerationOptions(new List<string>()))
+ {
+ z3 = ctx;
+
+ this.z3log = null;
+ this.tm = new Z3TypeCachedBuilder(this);
+ this.namer = new UniqueNamer();
+
+ // For external
+
+ constants_inv = new BacktrackDictionary<Term, VCExpr>();
+ functions_inv = new BacktrackDictionary<FuncDecl, Function>();
+ }
+
+ public Term VCExprToTerm(VCExpr expr, LineariserOptions linOptions) {
+ Z3apiExprLineariser visitor = new Z3apiExprLineariser(this, namer);
+ return (Term)expr.Accept(visitor, linOptions);
+ }
+
+
+ private class fromZ3
+ {
+ private VCExpressionGenerator gen;
+ private Dictionary<Term, VCExpr> memo;
+ private BacktrackDictionary<Term, VCExpr> constants_inv;
+ private BacktrackDictionary<FuncDecl, Function> functions_inv;
+ private List<VCExprLetBinding> lets;
+ private int let_ctr = 0;
+
+ private VCExpr create_let(Term t, VCExpr u)
+ {
+ var name = "$x" + let_ctr.ToString();
+ let_ctr++;
+ var sym = gen.Variable(name, u.Type);
+ memo.Remove(t);
+ memo.Add(t, sym);
+ lets.Add(gen.LetBinding(sym, u));
+ return sym;
+ }
+
+ public fromZ3(VCExpressionGenerator _gen,
+ BacktrackDictionary<Term, VCExpr> _constants_inv,
+ BacktrackDictionary<FuncDecl, Function> _functions_inv)
+ {
+ gen = _gen;
+ constants_inv = _constants_inv;
+ functions_inv = _functions_inv;
+ memo = new Dictionary<Term, VCExpr>();
+ lets = new List<VCExprLetBinding>();
+ }
+
+ public void clear()
+ {
+ memo.Clear();
+ lets.Clear();
+ }
+ public VCExpr get(Term arg)
+ {
+ if (memo.ContainsKey(arg))
+ return memo[arg];
+ VCExpr res = null;
+ switch (arg.GetKind())
+ {
+ case TermKind.Numeral:
+ var numstr = arg.GetNumeralString();
+ var bignum = Basetypes.BigNum.FromString(numstr);
+ res = gen.Integer(bignum);
+ break;
+ case TermKind.App:
+ var args = arg.GetAppArgs();
+ var vcargs = new VCExpr[args.Length];
+ for (int i = 0; i < args.Length; i++)
+ vcargs[i] = get(args[i]);
+
+ switch (arg.GetAppDecl().GetKind())
+ {
+ case DeclKind.Add:
+ if (vcargs.Length == 0)
+ res = gen.Integer(Basetypes.BigNum.FromInt(0));
+ else
+ {
+ res = vcargs[0];
+ for (int k = 1; k < vcargs.Length; k++)
+ res = gen.Add(res, vcargs[k]);
+ }
+ break;
+ case DeclKind.And:
+ res = VCExpressionGenerator.True;
+ for (int i = 0; i < vcargs.Length; i++)
+ res = gen.AndSimp(res, vcargs[i]);
+ break;
+ case DeclKind.Div:
+ Debug.Assert(vcargs.Length == 2);
+ res = gen.Function(VCExpressionGenerator.DivOp, vcargs[0], vcargs[1]);
+ break;
+ case DeclKind.Eq:
+ Debug.Assert(vcargs.Length == 2);
+ res = gen.Eq(vcargs[0], vcargs[1]);
+ break;
+ case DeclKind.False:
+ res = VCExpressionGenerator.False;
+ break;
+ case DeclKind.Ge:
+ Debug.Assert(vcargs.Length == 2);
+ res = gen.Function(VCExpressionGenerator.GeOp, vcargs[0], vcargs[1]);
+ break;
+ case DeclKind.Gt:
+ Debug.Assert(vcargs.Length == 2);
+ res = gen.Gt(vcargs[0], vcargs[1]);
+ break;
+ case DeclKind.IDiv:
+ Debug.Assert(vcargs.Length == 2);
+ res = gen.Function(VCExpressionGenerator.DivOp, vcargs[0], vcargs[1]);
+ break;
+ case DeclKind.Iff:
+ Debug.Assert(vcargs.Length == 2);
+ var l = create_let(args[0], vcargs[0]);
+ var r = create_let(args[1], vcargs[1]);
+ return gen.And(gen.Implies(l, r), gen.Implies(r, l));
+ case DeclKind.Implies:
+ Debug.Assert(vcargs.Length == 2);
+ res = gen.Implies(vcargs[0], vcargs[1]);
+ break;
+ case DeclKind.Ite:
+ Debug.Assert(vcargs.Length == 3);
+ res = gen.Function(VCExpressionGenerator.IfThenElseOp, vcargs[0], vcargs[1], vcargs[2]);
+ break;
+ case DeclKind.Le:
+ Debug.Assert(vcargs.Length == 2);
+ res = gen.Function(VCExpressionGenerator.LeOp, vcargs[0], vcargs[1]);
+ break;
+ case DeclKind.Lt:
+ Debug.Assert(vcargs.Length == 2);
+ res = gen.Function(VCExpressionGenerator.LtOp, vcargs[0], vcargs[1]);
+ break;
+ case DeclKind.Mod:
+ Debug.Assert(vcargs.Length == 2);
+ res = gen.Function(VCExpressionGenerator.ModOp, vcargs[0], vcargs[1]);
+ break;
+ case DeclKind.Mul:
+ Debug.Assert(vcargs.Length == 2);
+ res = gen.Function(VCExpressionGenerator.MulOp, vcargs[0], vcargs[1]);
+ break;
+ case DeclKind.Not:
+ Debug.Assert(vcargs.Length == 1);
+ res = gen.Not(vcargs[0]);
+ break;
+ case DeclKind.Or:
+ res = VCExpressionGenerator.False;
+ for (int i = 0; i < vcargs.Length; i++)
+ res = gen.OrSimp(res, vcargs[i]);
+ break;
+ case DeclKind.Select:
+ Debug.Assert(vcargs.Length == 2);
+ res = gen.Select(vcargs[0], vcargs[1]);
+ break;
+ case DeclKind.Store:
+ Debug.Assert(vcargs.Length == 3);
+ res = gen.Store(vcargs[0], vcargs[1], vcargs[2]);
+ break;
+ case DeclKind.Sub:
+ Debug.Assert(vcargs.Length == 2);
+ res = gen.Function(VCExpressionGenerator.SubOp, vcargs[0], vcargs[1]);
+ break;
+ case DeclKind.True:
+ res = VCExpressionGenerator.True;
+ break;
+ case DeclKind.Uminus:
+ Debug.Assert(vcargs.Length == 1);
+ var bigzero = Basetypes.BigNum.FromInt(0);
+ res = gen.Function(VCExpressionGenerator.SubOp, gen.Integer(bigzero), vcargs[0]);
+ break;
+ case DeclKind.Uninterpreted:
+ var name = arg.GetAppDecl().GetDeclName();
+ if (args.Length == 0)
+ { // a 0-ary constant is a VCExprVar
+ if (!constants_inv.TryGetValue(arg, out res))
+ throw new Exception("Z3 returned unknown constant: " + name);
+ }
+ else
+ {
+ Function f;
+ if (!functions_inv.TryGetValue(arg.GetAppDecl(), out f))
+ throw new Exception("Z3 returned unknown function: " + name);
+ List<VCExpr> vcargsList = new List<VCExpr>(vcargs);
+ res = gen.Function(f, vcargsList);
+ }
+ break;
+ default:
+ throw new Exception("Unknown Z3 operator");
+ }
+ break;
+ default:
+ Debug.Assert(false);
+ throw new Exception("Unknown Z3 AST kind");
+ }
+
+ memo.Add(arg, res);
+ return res;
+ }
+ public VCExpr add_lets(VCExpr e)
+ {
+ foreach (var let in lets)
+ {
+ e = gen.Let(e, let);
+ }
+ return e;
+ }
+ }
+
+ public VCExpr TermToVCExpr(Term t)
+ {
+ var fZ = new fromZ3(gen, constants_inv, functions_inv);
+ return fZ.add_lets(fZ.get(t));
+ }
+
+
+
+
+
public override void DeclareType(TypeCtorDecl t, string attributes) {
base.DeclareType(t, attributes);
log("(declare-sort {0})", t.Name);
@@ -97,6 +326,7 @@ namespace Microsoft.Boogie.Z3 { Sort rangeAst = tm.GetType(range);
FuncDecl constDeclAst = z3.MkFuncDecl(symbolAst, domainAst.ToArray(), rangeAst);
functions.Add(functionName, constDeclAst);
+ if(functions_inv != null)functions_inv.Add(constDeclAst, f);
log("(declare-funs (({0} {1} {2})))", functionName, domainStr, rangeAst);
}
@@ -122,7 +352,11 @@ namespace Microsoft.Boogie.Z3 { }
public void CloseLog() {
- z3.CloseLog();
+#if true
+ Z3Log.Close();
+#else
+ z3.CloseLog();
+#endif
if (z3log != null) {
z3log.Close();
}
@@ -134,6 +368,8 @@ namespace Microsoft.Boogie.Z3 { constants.CreateBacktrackPoint();
functions.CreateBacktrackPoint();
labels.CreateBacktrackPoint();
+ if(constants_inv != null)constants_inv.CreateBacktrackPoint();
+ if(functions_inv != null)functions_inv.CreateBacktrackPoint();
z3.Push();
log("(push)");
}
@@ -144,6 +380,8 @@ namespace Microsoft.Boogie.Z3 { functions.Backtrack();
constants.Backtrack();
symbols.Backtrack();
+ if (constants_inv != null) constants_inv.Backtrack();
+ if (functions_inv != null) functions_inv.Backtrack();
log("(pop)");
}
@@ -368,13 +606,18 @@ namespace Microsoft.Boogie.Z3 { return result;
}
- public Term GetConstant(string constantName, Type constantType) {
+ public Term GetConstant(string constantName, Type constantType, VCExpr node)
+ {
Term typeSafeTerm;
if (!constants.ContainsKey(constantName))
this.DeclareConstant(constantName, constantType);
if (!constants.TryGetValue(constantName, out typeSafeTerm))
throw new Exception("constant " + constantName + " is not defined");
+
+ if (constants_inv != null && !constants_inv.ContainsKey(typeSafeTerm))
+ constants_inv.Add(typeSafeTerm, node);
+
return typeSafeTerm;
}
diff --git a/Source/Provers/Z3api/VCExprVisitor.cs b/Source/Provers/Z3api/VCExprVisitor.cs index 149a23f1..0605a854 100644 --- a/Source/Provers/Z3api/VCExprVisitor.cs +++ b/Source/Provers/Z3api/VCExprVisitor.cs @@ -188,7 +188,7 @@ namespace Microsoft.Boogie.Z3 else
{
string varName = namer.GetName(node, node.Name);
- return cm.GetConstant(varName, node.Type);
+ return cm.GetConstant(varName, node.Type,node);
}
}
@@ -252,7 +252,7 @@ namespace Microsoft.Boogie.Z3 private Term MakeQuantifier(bool isForall, uint weight, string qid, int skolemid, List<string> varNames, List<Type> boogieTypes, List<Pattern> patterns, List<Term> no_patterns, Term body) {
List<Term> bound = new List<Term>();
for (int i = 0; i < varNames.Count; i++) {
- Term t = cm.GetConstant(varNames[i], boogieTypes[i]);
+ Term t = cm.GetConstant(varNames[i], boogieTypes[i], null);
bound.Add(t);
}
diff --git a/Source/Provers/Z3api/Z3api.csproj b/Source/Provers/Z3api/Z3api.csproj index 7c481438..f9511dbd 100644 --- a/Source/Provers/Z3api/Z3api.csproj +++ b/Source/Provers/Z3api/Z3api.csproj @@ -118,9 +118,8 @@ </Target>
-->
<ItemGroup>
- <Reference Include="Microsoft.Z3, Version=2.0.40827.2, Culture=neutral, PublicKeyToken=9c8d792caae602a2, processorArchitecture=x86">
- <SpecificVersion>False</SpecificVersion>
- <HintPath>..\..\..\Binaries\Microsoft.Z3.dll</HintPath>
+ <Reference Include="ManagedAPI">
+ <HintPath>..\..\..\..\..\iZ3\win\iZ3\Debug\ManagedAPI.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core">
diff --git a/Source/VCGeneration/Check.cs b/Source/VCGeneration/Check.cs index a2564be5..e3b1cb2d 100644 --- a/Source/VCGeneration/Check.cs +++ b/Source/VCGeneration/Check.cs @@ -100,8 +100,9 @@ namespace Microsoft.Boogie { /// <summary>
/// Constructor. Initialize a checker with the program and log file.
+ /// Optionally, use prover context provided by parameter "ctx".
/// </summary>
- public Checker(VC.ConditionGeneration vcgen, Program prog, string/*?*/ logFilePath, bool appendLogFile, int timeout) {
+ public Checker(VC.ConditionGeneration vcgen, Program prog, string/*?*/ logFilePath, bool appendLogFile, int timeout, ProverContext ctx = null) {
Contract.Requires(vcgen != null);
Contract.Requires(prog != null);
this.timeout = timeout;
@@ -121,7 +122,6 @@ namespace Microsoft.Boogie { options.Parse(CommandLineOptions.Clo.ProverOptions);
ContextCacheKey key = new ContextCacheKey(prog);
- ProverContext ctx;
ProverInterface prover;
if (vcgen.CheckerCommonState == null) {
@@ -129,12 +129,13 @@ namespace Microsoft.Boogie { }
IDictionary<ContextCacheKey, ProverContext>/*!>!*/ cachedContexts = (IDictionary<ContextCacheKey, ProverContext/*!*/>)vcgen.CheckerCommonState;
- if (cachedContexts.TryGetValue(key, out ctx)) {
+ if (ctx == null && cachedContexts.TryGetValue(key, out ctx))
+ {
ctx = (ProverContext)cce.NonNull(ctx).Clone();
prover = (ProverInterface)
CommandLineOptions.Clo.TheProverFactory.SpawnProver(options, ctx);
} else {
- ctx = (ProverContext)CommandLineOptions.Clo.TheProverFactory.NewProverContext(options);
+ if (ctx == null) ctx = (ProverContext)CommandLineOptions.Clo.TheProverFactory.NewProverContext(options);
// set up the context
foreach (Declaration decl in prog.TopLevelDeclarations) {
@@ -488,7 +489,7 @@ namespace Microsoft.Boogie { get;
}
- public virtual void DefineMacro(Function fun, VCExpr vc) {
+ public virtual void DefineMacro(Macro fun, VCExpr vc) {
throw new NotImplementedException();
}
}
diff --git a/Source/VCGeneration/ConditionGeneration.cs b/Source/VCGeneration/ConditionGeneration.cs index ba58a5de..9837626d 100644 --- a/Source/VCGeneration/ConditionGeneration.cs +++ b/Source/VCGeneration/ConditionGeneration.cs @@ -206,11 +206,23 @@ namespace Microsoft.Boogie { }
}
+ void ApplyRedirections(Model m) {
+ var mapping = new Dictionary<Model.Element, Model.Element>();
+ foreach (var name in new string[] { "U_2_bool", "U_2_int" }) {
+ Model.Func f = m.TryGetFunc(name);
+ if (f != null && f.Arity == 1) {
+ foreach (var ft in f.Apps) mapping[ft.Args[0]] = ft.Result;
+ }
+ }
+ m.Substitute(mapping);
+ }
+
public Model GetModelWithStates()
{
if (Model == null) return null;
Model m = Model;
+ ApplyRedirections(m);
var mvstates = m.TryGetFunc("@MV_state");
if (MvInfo == null || mvstates == null)
diff --git a/Source/VCGeneration/StratifiedVC.cs b/Source/VCGeneration/StratifiedVC.cs index 563cbf40..a2ad1bd3 100644 --- a/Source/VCGeneration/StratifiedVC.cs +++ b/Source/VCGeneration/StratifiedVC.cs @@ -15,7 +15,7 @@ using Microsoft.Boogie.VCExprAST; namespace VC {
using Bpl = Microsoft.Boogie;
-
+
public class StratifiedVC {
public StratifiedInliningInfo info;
public int id;
@@ -23,44 +23,22 @@ namespace VC { public Dictionary<Block, List<StratifiedCallSite>> callSites;
public Dictionary<Block, List<StratifiedCallSite>> recordProcCallSites;
public VCExpr vcexpr;
- public Dictionary<Block, VCExprVar> reachVars;
+
+ // the following three fields are not being used at the moment
+ public VCExprVar entryExprVar;
+ public Dictionary<Block, Macro> reachMacros;
+ public Dictionary<Block, VCExpr> reachMacroDefinitions;
public StratifiedVC(StratifiedInliningInfo siInfo) {
info = siInfo;
info.GenerateVC();
- vcexpr = info.vcexpr;
var vcgen = info.vcgen;
var prover = vcgen.prover;
VCExpressionGenerator gen = prover.VCExprGen;
- var bet = prover.Context.BoogieExprTranslator;
- VCExpr controlFlowVariableExpr = bet.LookupVariable(info.controlFlowVariable);
+ var bet = prover.Context.BoogieExprTranslator;
+
+ vcexpr = info.vcexpr;
id = vcgen.CreateNewId();
- VCExpr eqExpr = gen.Eq(controlFlowVariableExpr, gen.Integer(BigNum.FromInt(id)));
- vcexpr = gen.And(eqExpr, vcexpr);
-
- var impl = info.impl;
- reachVars = new Dictionary<Block, VCExprVar>();
- Dictionary<Block, VCExpr> reachExprs = new Dictionary<Block, VCExpr>();
- foreach (Block b in impl.Blocks) {
- reachVars[b] = vcgen.CreateNewVar(Bpl.Type.Bool);
- reachExprs[b] = VCExpressionGenerator.False;
- }
- foreach (Block currBlock in impl.Blocks) {
- GotoCmd gotoCmd = currBlock.TransferCmd as GotoCmd;
- if (gotoCmd == null) continue;
- foreach (Block successorBlock in gotoCmd.labelTargets) {
- VCExpr controlFlowFunctionAppl = gen.ControlFlowFunctionApplication(controlFlowVariableExpr, gen.Integer(BigNum.FromInt(currBlock.UniqueId)));
- VCExpr controlTransferExpr = gen.Eq(controlFlowFunctionAppl, gen.Integer(BigNum.FromInt(successorBlock.UniqueId)));
- reachExprs[successorBlock] = gen.Or(reachExprs[successorBlock], gen.And(reachVars[currBlock], controlTransferExpr));
- }
- }
- // The binding for entry block should be left defined;
- // it will get filled in when the call tree is constructed
- for (int i = 1; i < impl.Blocks.Count; i++) {
- Block b = impl.Blocks[i];
- vcexpr = gen.And(vcexpr, gen.Eq(reachVars[b], reachExprs[b]));
- }
-
interfaceExprVars = new List<VCExprVar>();
Dictionary<VCExprVar, VCExpr> substDict = new Dictionary<VCExprVar, VCExpr>();
foreach (VCExprVar v in info.interfaceExprVars) {
@@ -71,15 +49,35 @@ namespace VC { foreach (VCExprVar v in info.privateExprVars) {
substDict.Add(v, vcgen.CreateNewVar(v.Type));
}
+ substDict.Add(bet.LookupVariable(info.controlFlowVariable), gen.Integer(BigNum.FromInt(id)));
VCExprSubstitution subst = new VCExprSubstitution(substDict, new Dictionary<TypeVariable, Microsoft.Boogie.Type>());
SubstitutingVCExprVisitor substVisitor = new SubstitutingVCExprVisitor(prover.VCExprGen);
vcexpr = substVisitor.Mutate(vcexpr, subst);
+ var impl = info.impl;
+ reachMacros = new Dictionary<Block, Macro>();
+ reachMacroDefinitions = new Dictionary<Block, VCExpr>();
+ foreach (Block b in impl.Blocks) {
+ reachMacros[b] = vcgen.CreateNewMacro();
+ reachMacroDefinitions[b] = VCExpressionGenerator.False;
+ }
+ entryExprVar = vcgen.CreateNewVar(Microsoft.Boogie.Type.Bool);
+ reachMacroDefinitions[impl.Blocks[0]] = entryExprVar;
+ foreach (Block currBlock in impl.Blocks) {
+ GotoCmd gotoCmd = currBlock.TransferCmd as GotoCmd;
+ if (gotoCmd == null) continue;
+ foreach (Block successorBlock in gotoCmd.labelTargets) {
+ VCExpr controlFlowFunctionAppl = gen.ControlFlowFunctionApplication(gen.Integer(BigNum.FromInt(id)), gen.Integer(BigNum.FromInt(currBlock.UniqueId)));
+ VCExpr controlTransferExpr = gen.Eq(controlFlowFunctionAppl, gen.Integer(BigNum.FromInt(successorBlock.UniqueId)));
+ reachMacroDefinitions[successorBlock] = gen.Or(reachMacroDefinitions[successorBlock], gen.And(gen.Function(reachMacros[currBlock]), controlTransferExpr));
+ }
+ }
+
callSites = new Dictionary<Block, List<StratifiedCallSite>>();
foreach (Block b in info.callSites.Keys) {
callSites[b] = new List<StratifiedCallSite>();
foreach (CallSite cs in info.callSites[b]) {
- callSites[b].Add(new StratifiedCallSite(cs, substVisitor, subst, reachVars));
+ callSites[b].Add(new StratifiedCallSite(cs, substVisitor, subst));
}
}
@@ -87,7 +85,7 @@ namespace VC { foreach (Block b in info.recordProcCallSites.Keys) {
recordProcCallSites[b] = new List<StratifiedCallSite>();
foreach (CallSite cs in info.recordProcCallSites[b]) {
- recordProcCallSites[b].Add(new StratifiedCallSite(cs, substVisitor, subst, reachVars));
+ recordProcCallSites[b].Add(new StratifiedCallSite(cs, substVisitor, subst));
}
}
}
@@ -103,6 +101,18 @@ namespace VC { return ret;
}
}
+
+ public List<StratifiedCallSite> RecordProcCallSites {
+ get {
+ var ret = new List<StratifiedCallSite>();
+ foreach (var b in recordProcCallSites.Keys) {
+ foreach (var cs in recordProcCallSites[b]) {
+ ret.Add(cs);
+ }
+ }
+ return ret;
+ }
+ }
}
public class CallSite {
@@ -110,9 +120,11 @@ namespace VC { public List<VCExpr> interfaceExprs;
public Block block;
public int numInstr; // for TraceLocation
- public CallSite(string callee, List<VCExpr> interfaceExprs, Block block, int numInstr) {
+ public VCExprVar callSiteVar;
+ public CallSite(string callee, List<VCExpr> interfaceExprs, VCExprVar callSiteVar, Block block, int numInstr) {
this.calleeName = callee;
this.interfaceExprs = interfaceExprs;
+ this.callSiteVar = callSiteVar;
this.block = block;
this.numInstr = numInstr;
}
@@ -121,26 +133,47 @@ namespace VC { public class StratifiedCallSite {
public CallSite callSite;
public List<VCExpr> interfaceExprs;
- public VCExprVar reachVar;
+ public VCExpr callSiteExpr;
- public StratifiedCallSite(CallSite cs, SubstitutingVCExprVisitor substVisitor, VCExprSubstitution subst, Dictionary<Block, VCExprVar> reachVars) {
+ public StratifiedCallSite(CallSite cs, SubstitutingVCExprVisitor substVisitor, VCExprSubstitution subst) {
callSite = cs;
interfaceExprs = new List<VCExpr>();
foreach (VCExpr v in cs.interfaceExprs) {
interfaceExprs.Add(substVisitor.Mutate(v, subst));
}
- reachVar = reachVars[cs.block];
+ if (callSite.callSiteVar != null)
+ callSiteExpr = substVisitor.Mutate(callSite.callSiteVar, subst);
}
public VCExpr Attach(StratifiedVC svc) {
Contract.Assert(interfaceExprs.Count == svc.interfaceExprVars.Count);
StratifiedInliningInfo info = svc.info;
- VCExpressionGenerator gen = info.vcgen.prover.VCExprGen;
- VCExpr ret = gen.Eq(reachVar, svc.reachVars[info.impl.Blocks[0]]);
- for (int i = 0; i < interfaceExprs.Count; i++) {
- ret = gen.And(ret, gen.Eq(interfaceExprs[i], svc.interfaceExprVars[i]));
+ ProverInterface prover = info.vcgen.prover;
+ VCExpressionGenerator gen = prover.VCExprGen;
+
+ Dictionary<VCExprVar, VCExpr> substDict = new Dictionary<VCExprVar, VCExpr>();
+ for (int i = 0; i < svc.interfaceExprVars.Count; i++) {
+ VCExprVar v = svc.interfaceExprVars[i];
+ substDict.Add(v, interfaceExprs[i]);
}
- return ret;
+ VCExprSubstitution subst = new VCExprSubstitution(substDict, new Dictionary<TypeVariable, Microsoft.Boogie.Type>());
+ SubstitutingVCExprVisitor substVisitor = new SubstitutingVCExprVisitor(prover.VCExprGen);
+ svc.vcexpr = substVisitor.Mutate(svc.vcexpr, subst);
+ foreach (StratifiedCallSite scs in svc.CallSites) {
+ List<VCExpr> newInterfaceExprs = new List<VCExpr>();
+ foreach (VCExpr expr in scs.interfaceExprs) {
+ newInterfaceExprs.Add(substVisitor.Mutate(expr, subst));
+ }
+ scs.interfaceExprs = newInterfaceExprs;
+ }
+ foreach (StratifiedCallSite scs in svc.RecordProcCallSites) {
+ List<VCExpr> newInterfaceExprs = new List<VCExpr>();
+ foreach (VCExpr expr in scs.interfaceExprs) {
+ newInterfaceExprs.Add(substVisitor.Mutate(expr, subst));
+ }
+ scs.interfaceExprs = newInterfaceExprs;
+ }
+ return gen.Implies(callSiteExpr, svc.vcexpr);
}
}
@@ -149,7 +182,7 @@ namespace VC { public Implementation impl;
public Function function;
public Variable controlFlowVariable;
- public Expr assertExpr;
+ public AssertCmd exitAssertCmd;
public VCExpr vcexpr;
public List<VCExprVar> interfaceExprVars;
public List<VCExprVar> privateExprVars;
@@ -209,7 +242,7 @@ namespace VC { public void GenerateVC() {
if (initialized) return;
List<Variable> outputVariables = new List<Variable>();
- assertExpr = new LiteralExpr(Token.NoToken, true);
+ Expr assertExpr = new LiteralExpr(Token.NoToken, true);
foreach (Variable v in impl.OutParams) {
Constant c = new Constant(Token.NoToken, new TypedIdent(Token.NoToken, impl.Name + "_" + v.Name, v.TypedIdent.Type));
outputVariables.Add(c);
@@ -224,26 +257,29 @@ namespace VC { Expr eqExpr = Expr.Eq(new IdentifierExpr(Token.NoToken, c), new IdentifierExpr(Token.NoToken, v));
assertExpr = Expr.And(assertExpr, eqExpr);
}
- assertExpr = Expr.Not(assertExpr);
+ exitAssertCmd = new AssertCmd(Token.NoToken, Expr.Not(assertExpr));
Program program = vcgen.program;
ProverInterface proverInterface = vcgen.prover;
vcgen.ConvertCFG2DAG(impl);
- ModelViewInfo mvInfo;
vcgen.PassifyImpl(impl, out mvInfo);
- controlFlowVariable = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, "@cfc", Microsoft.Boogie.Type.Int));
- impl.LocVars.Add(controlFlowVariable);
-
VCExpressionGenerator gen = proverInterface.VCExprGen;
var exprGen = proverInterface.Context.ExprGen;
var translator = proverInterface.Context.BoogieExprTranslator;
- VCExpr controlFlowVariableExpr = CommandLineOptions.Clo.UseLabels ? null : translator.LookupVariable(controlFlowVariable);
+ VCExpr controlFlowVariableExpr = null;
+ if (!CommandLineOptions.Clo.UseLabels) {
+ controlFlowVariable = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, "@cfc", Microsoft.Boogie.Type.Int));
+ controlFlowVariableExpr = translator.LookupVariable(controlFlowVariable);
+ vcgen.InstrumentCallSites(impl);
+ }
vcexpr = gen.Not(vcgen.GenerateVC(impl, controlFlowVariableExpr, out label2absy, proverInterface.Context));
if (controlFlowVariableExpr != null) {
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);
+ callSites = vcgen.CollectCallSites(impl);
+ recordProcCallSites = vcgen.CollectRecordProcedureCallSites(impl);
}
privateExprVars = new List<VCExprVar>();
@@ -265,51 +301,10 @@ namespace VC { interfaceExprVars.Add(translator.LookupVariable(v));
}
- callSites = vcgen.CollectCallSites(impl);
- recordProcCallSites = vcgen.CollectRecordProcedureCallSites(impl);
initialized = true;
}
}
- public class CallSitesSimplifier : StandardVisitor {
- VariableSeq localVars;
- StratifiedVCGenBase vcgen;
- public static void SimplifyCallSites(Implementation implementation, StratifiedVCGenBase vcgen) {
- CallSitesSimplifier visitor = new CallSitesSimplifier(vcgen);
- visitor.Visit(implementation);
- implementation.LocVars.AddRange(visitor.localVars);
- }
- private CallSitesSimplifier(StratifiedVCGenBase vcgen) {
- this.vcgen = vcgen;
- this.localVars = new VariableSeq();
- }
- public override CmdSeq VisitCmdSeq(CmdSeq cmdSeq) {
- CmdSeq newCmdSeq = new CmdSeq();
- foreach (Cmd cmd in cmdSeq) {
- AssumeCmd assumeCmd = cmd as AssumeCmd;
- if (assumeCmd == null) {
- newCmdSeq.Add(cmd);
- continue;
- }
- NAryExpr naryExpr = assumeCmd.Expr as NAryExpr;
- if (naryExpr == null || !vcgen.implName2StratifiedInliningInfo.ContainsKey(naryExpr.Fun.FunctionName)) {
- newCmdSeq.Add(cmd);
- continue;
- }
-
- ExprSeq exprs = new ExprSeq();
- foreach (Expr e in naryExpr.Args) {
- LocalVariable newVar = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, "CallSiteSimplification@" + localVars.Length, e.Type));
- localVars.Add(newVar);
- newCmdSeq.Add(new AssumeCmd(Token.NoToken, Expr.Eq(Expr.Ident(newVar), e)));
- exprs.Add(Expr.Ident(newVar));
- }
- newCmdSeq.Add(new AssumeCmd(Token.NoToken, new NAryExpr(Token.NoToken, naryExpr.Fun, exprs)));
- }
- return newCmdSeq;
- }
- }
-
public abstract class StratifiedVCGenBase : VCGen {
public readonly static string recordProcName = "boogie_si_record";
public Dictionary<string, StratifiedInliningInfo> implName2StratifiedInliningInfo;
@@ -362,11 +357,33 @@ namespace VC { base.Close();
}
+ public void InstrumentCallSites(Implementation implementation) {
+ var callSiteId = 0;
+ foreach (Block block in implementation.Blocks) {
+ CmdSeq newCmds = new CmdSeq();
+ for (int i = 0; i < block.Cmds.Length; i++) {
+ Cmd cmd = block.Cmds[i];
+ newCmds.Add(cmd);
+ AssumeCmd assumeCmd = cmd as AssumeCmd;
+ if (assumeCmd == null) continue;
+ NAryExpr naryExpr = assumeCmd.Expr as NAryExpr;
+ if (naryExpr == null) continue;
+ if (!implName2StratifiedInliningInfo.ContainsKey(naryExpr.Fun.FunctionName)) continue;
+ Variable callSiteVar = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, "StratifiedInliningCallSite" + callSiteId, Microsoft.Boogie.Type.Bool));
+ implementation.LocVars.Add(callSiteVar);
+ newCmds.Add(new AssumeCmd(Token.NoToken, new IdentifierExpr(Token.NoToken, callSiteVar)));
+ callSiteId++;
+ }
+ block.Cmds = newCmds;
+ }
+ }
+
public Dictionary<Block, List<CallSite>> CollectCallSites(Implementation implementation) {
var callSites = new Dictionary<Block, List<CallSite>>();
foreach (Block block in implementation.Blocks) {
for (int i = 0; i < block.Cmds.Length; i++) {
- AssumeCmd assumeCmd = block.Cmds[i] as AssumeCmd;
+ Cmd cmd = block.Cmds[i];
+ AssumeCmd assumeCmd = cmd as AssumeCmd;
if (assumeCmd == null) continue;
NAryExpr naryExpr = assumeCmd.Expr as NAryExpr;
if (naryExpr == null) continue;
@@ -375,7 +392,11 @@ namespace VC { foreach (Expr e in naryExpr.Args) {
interfaceExprs.Add(prover.Context.BoogieExprTranslator.Translate(e));
}
- CallSite cs = new CallSite(naryExpr.Fun.FunctionName, interfaceExprs, block, i);
+ int instr = i;
+ i++;
+ AssumeCmd callSiteAssumeCmd = (AssumeCmd)block.Cmds[i];
+ IdentifierExpr iexpr = (IdentifierExpr) callSiteAssumeCmd.Expr;
+ CallSite cs = new CallSite(naryExpr.Fun.FunctionName, interfaceExprs, prover.Context.BoogieExprTranslator.LookupVariable(iexpr.Decl), block, instr);
if (!callSites.ContainsKey(block))
callSites[block] = new List<CallSite>();
callSites[block].Add(cs);
@@ -397,7 +418,7 @@ namespace VC { foreach (Expr e in naryExpr.Args) {
interfaceExprs.Add(prover.Context.BoogieExprTranslator.Translate(e));
}
- CallSite cs = new CallSite(naryExpr.Fun.FunctionName, interfaceExprs, block, i);
+ CallSite cs = new CallSite(naryExpr.Fun.FunctionName, interfaceExprs, null, block, i);
if (!callSites.ContainsKey(block))
callSites[block] = new List<CallSite>();
callSites[block].Add(cs);
@@ -406,10 +427,16 @@ namespace VC { return callSites;
}
- private int newVarCountForStratifiedInlining = 0;
+ private int macroCountForStratifiedInlining = 0;
+ public Macro CreateNewMacro() {
+ string newName = "StratifiedInliningMacro@" + macroCountForStratifiedInlining.ToString();
+ macroCountForStratifiedInlining++;
+ return new Macro(Token.NoToken, newName, new VariableSeq(), new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "", Microsoft.Boogie.Type.Bool), false));
+ }
+ private int varCountForStratifiedInlining = 0;
public VCExprVar CreateNewVar(Microsoft.Boogie.Type type) {
- string newName = "StratifiedInlining@" + newVarCountForStratifiedInlining.ToString();
- newVarCountForStratifiedInlining++;
+ string newName = "StratifiedInliningVar@" + varCountForStratifiedInlining.ToString();
+ varCountForStratifiedInlining++;
Constant newVar = new Constant(Token.NoToken, new TypedIdent(Token.NoToken, newName, type));
prover.Context.DeclareConstant(newVar, false, null);
return prover.VCExprGen.Variable(newVar.Name, type);
@@ -422,9 +449,9 @@ namespace VC { // Used inside PassifyImpl
protected override void addExitAssert(string implName, Block exitBlock) {
if (implName2StratifiedInliningInfo != null && implName2StratifiedInliningInfo.ContainsKey(implName)) {
- Expr assertExpr = implName2StratifiedInliningInfo[implName].assertExpr;
- Contract.Assert(assertExpr != null);
- exitBlock.Cmds.Add(new AssertCmd(Token.NoToken, assertExpr));
+ AssertCmd exitAssertCmd = implName2StratifiedInliningInfo[implName].exitAssertCmd;
+ Contract.Assert(exitAssertCmd != null);
+ exitBlock.Cmds.Add(exitAssertCmd);
}
}
diff --git a/Test/VSComp2010/runtest.bat b/Test/VSComp2010/runtest.bat index 9535d677..63f5df23 100644 --- a/Test/VSComp2010/runtest.bat +++ b/Test/VSComp2010/runtest.bat @@ -3,8 +3,6 @@ setlocal set BOOGIEDIR=..\..\Binaries
set DAFNY_EXE=%BOOGIEDIR%\Dafny.exe
-set BPLEXE=%BOOGIEDIR%\Boogie.exe
-set CSC=c:/Windows/Microsoft.NET/Framework/v4.0.30319/csc.exe
for %%f in (Problem1-SumMax.dfy Problem2-Invert.dfy
Problem3-FindZero.dfy Problem4-Queens.dfy
diff --git a/Test/VSI-Benchmarks/runtest.bat b/Test/VSI-Benchmarks/runtest.bat index 611f9251..f5b9d1b9 100644 --- a/Test/VSI-Benchmarks/runtest.bat +++ b/Test/VSI-Benchmarks/runtest.bat @@ -3,8 +3,6 @@ setlocal set BOOGIEDIR=..\..\Binaries
set DAFNY_EXE=%BOOGIEDIR%\Dafny.exe
-set BPLEXE=%BOOGIEDIR%\Boogie.exe
-set CSC=c:/Windows/Microsoft.NET/Framework/v4.0.30319/csc.exe
for %%f in (b1.dfy b2.dfy b3.dfy b4.dfy b5.dfy b6.dfy b7.dfy b8.dfy) do (
echo.
diff --git a/Test/dafny0/Answer b/Test/dafny0/Answer index c451cc62..5f80df86 100644 --- a/Test/dafny0/Answer +++ b/Test/dafny0/Answer @@ -91,8 +91,10 @@ TypeTests.dfy(84,10): Error: cannot assign to a range of array elements (try the TypeTests.dfy(90,9): Error: sorry, cannot instantiate type parameter with a subrange type
TypeTests.dfy(91,8): Error: sorry, cannot instantiate 'array' type with a subrange type
TypeTests.dfy(92,8): Error: sorry, cannot instantiate 'array' type with a subrange type
+TypeTests.dfy(116,4): Error: cannot assign to non-ghost variable in a ghost context
+TypeTests.dfy(117,7): Error: cannot assign to non-ghost variable in a ghost context
TypeTests.dfy(18,9): Error: because of cyclic dependencies among constructor argument types, no instances of datatype 'NeverendingList' can be constructed
-34 resolution/type errors detected in TypeTests.dfy
+36 resolution/type errors detected in TypeTests.dfy
-------------------- NatTypes.dfy --------------------
NatTypes.dfy(7,5): Error: value assigned to a nat must be non-negative
@@ -280,7 +282,7 @@ Execution trace: (0,0): anon37_Then
(0,0): anon22
(0,0): anon38_Then
-SmallTests.dfy(584,18): Error: target object may be null
+SmallTests.dfy(584,25): Error: target object may be null
Execution trace:
(0,0): anon0
SmallTests.dfy(597,10): Error: assertion violation
@@ -712,13 +714,13 @@ Modules0.dfy(7,7): Error: Duplicate name of top-level declaration: WazzupA Modules0.dfy(10,7): Error: Duplicate name of top-level declaration: WazzupB
Modules0.dfy(11,8): Error: Duplicate name of top-level declaration: WazzupB
Modules0.dfy(12,11): Error: Duplicate name of top-level declaration: WazzupB
-Modules0.dfy(42,11): Error: The name T ambiguously refers to a type in one of the modules N, M
-Modules0.dfy(43,18): Error: The name T ambiguously refers to a type in one of the modules N, M
-Modules0.dfy(44,15): Error: The name T ambiguously refers to a type in one of the modules N, M
-Modules0.dfy(46,16): Error: The name T ambiguously refers to a type in one of the modules N, M
-Modules0.dfy(47,18): Error: The name T ambiguously refers to a type in one of the modules N, M
+Modules0.dfy(42,11): Error: The name T ambiguously refers to a type in one of the modules N, M (try qualifying the type name with the module name)
+Modules0.dfy(43,18): Error: The name T ambiguously refers to a type in one of the modules N, M (try qualifying the type name with the module name)
+Modules0.dfy(44,15): Error: The name T ambiguously refers to a type in one of the modules N, M (try qualifying the type name with the module name)
+Modules0.dfy(46,16): Error: The name T ambiguously refers to a type in one of the modules N, M (try qualifying the type name with the module name)
+Modules0.dfy(47,18): Error: The name T ambiguously refers to a type in one of the modules N, M (try qualifying the type name with the module name)
Modules0.dfy(43,13): Error: Function body type mismatch (expected T, got T)
-Modules0.dfy(48,19): Error: The name T ambiguously refers to a type in one of the modules N, M
+Modules0.dfy(48,19): Error: The name T ambiguously refers to a type in one of the modules N, M (try qualifying the type name with the module name)
Modules0.dfy(48,12): Error: new can be applied only to reference types (got T)
Modules0.dfy(54,12): Error: Undeclared top-level type or type parameter: T (did you forget a module import?)
Modules0.dfy(70,18): Error: Undeclared top-level type or type parameter: MyClass1 (did you forget a module import?)
@@ -730,13 +732,20 @@ Modules0.dfy(250,15): Error: unresolved identifier: X Modules0.dfy(251,17): Error: member DoesNotExist does not exist in class X
Modules0.dfy(294,16): Error: member R does not exist in class B
Modules0.dfy(294,6): Error: expected method call, found expression
+Modules0.dfy(317,18): Error: second argument to "in" must be a set or sequence with elements of type Q_Imp.Node, or a map with domain Q_Imp.Node (instead got set<Node>)
+Modules0.dfy(321,13): Error: arguments must have the same type (got Q_Imp.Node and Node)
+Modules0.dfy(322,11): Error: Undeclared module name: LongLostModule (did you forget a module import?)
+Modules0.dfy(323,11): Error: Undeclared module name: Wazzup (did you forget a module import?)
+Modules0.dfy(324,17): Error: Undeclared class name Edon in module Q_Imp
+Modules0.dfy(326,10): Error: new can be applied only to reference types (got Q_Imp.List<?>)
+Modules0.dfy(327,30): Error: member Create does not exist in class Klassy
Modules0.dfy(140,11): Error: ghost variables are allowed only in specification contexts
Modules0.dfy(154,11): Error: old expressions are allowed only in specification and ghost contexts
Modules0.dfy(155,11): Error: fresh expressions are allowed only in specification and ghost contexts
Modules0.dfy(156,11): Error: allocated expressions are allowed only in specification and ghost contexts
Modules0.dfy(172,10): Error: match source expression 'tree' has already been used as a match source expression in this context
Modules0.dfy(211,12): Error: match source expression 'l' has already been used as a match source expression in this context
-30 resolution/type errors detected in Modules0.dfy
+37 resolution/type errors detected in Modules0.dfy
-------------------- Modules1.dfy --------------------
Modules1.dfy(74,16): Error: assertion violation
@@ -758,7 +767,7 @@ Modules1.dfy(58,3): Error: failure to decrease termination measure Execution trace:
(0,0): anon0
-Dafny program verifier finished with 19 verified, 5 errors
+Dafny program verifier finished with 22 verified, 5 errors
-------------------- BadFunction.dfy --------------------
BadFunction.dfy(6,3): Error: failure to decrease termination measure
@@ -801,14 +810,7 @@ Basics.dfy(100,16): Error: assertion violation Execution trace:
(0,0): anon0
(0,0): anon10_Then
-Basics.dfy(113,12): Error: left-hand sides 0 and 1 may refer to the same location
-Execution trace:
- (0,0): anon0
- (0,0): anon3
- (0,0): anon11_Else
- (0,0): anon6
- (0,0): anon12_Then
-Basics.dfy(119,10): Error: left-hand sides 0 and 1 may refer to the same location
+Basics.dfy(119,10): Error: when left-hand sides 0 and 1 may refer to the same location, they must have the same value
Execution trace:
(0,0): anon0
(0,0): anon10_Then
@@ -817,7 +819,7 @@ Execution trace: (0,0): anon6
(0,0): anon12_Then
(0,0): anon9
-Basics.dfy(133,10): Error: left-hand sides 0 and 1 may refer to the same location
+Basics.dfy(133,10): Error: when left-hand sides 0 and 1 refer to the same location, they must have the same value
Execution trace:
(0,0): anon0
Basics.dfy(145,19): Error: assertion violation
@@ -848,8 +850,11 @@ Execution trace: (0,0): anon13_Then
(0,0): anon8
(0,0): anon14_Then
+Basics.dfy(226,10): Error: when left-hand sides 0 and 1 refer to the same location, they must have the same value
+Execution trace:
+ (0,0): anon0
-Dafny program verifier finished with 19 verified, 11 errors
+Dafny program verifier finished with 32 verified, 11 errors
-------------------- ControlStructures.dfy --------------------
ControlStructures.dfy(5,3): Error: missing case in case statement: Blue
@@ -1567,6 +1572,11 @@ Execution trace: Dafny program verifier finished with 30 verified, 2 errors
+-------------------- LiberalEquality.dfy --------------------
+LiberalEquality.dfy(37,14): Error: arguments must have the same type (got Weird<T,int,V> and Weird<T,bool,V>)
+LiberalEquality.dfy(52,14): Error: arguments must have the same type (got array<int> and array<bool>)
+2 resolution/type errors detected in LiberalEquality.dfy
+
-------------------- SmallTests.dfy --------------------
SmallTests.dfy(30,11): Error: index out of range
Execution trace:
@@ -1708,7 +1718,7 @@ Execution trace: (0,0): anon37_Then
(0,0): anon22
(0,0): anon38_Then
-SmallTests.dfy(584,18): Error: target object may be null
+SmallTests.dfy(584,25): Error: target object may be null
Execution trace:
(0,0): anon0
SmallTests.dfy(597,10): Error: assertion violation
@@ -1856,7 +1866,7 @@ Execution trace: (0,0): anon37_Then
(0,0): anon22
(0,0): anon38_Then
-out.tmp.dfy(530,18): Error: target object may be null
+out.tmp.dfy(530,25): Error: target object may be null
Execution trace:
(0,0): anon0
out.tmp.dfy(543,10): Error: assertion violation
diff --git a/Test/dafny0/Basics.dfy b/Test/dafny0/Basics.dfy index 6aa1e34d..7fca7199 100644 --- a/Test/dafny0/Basics.dfy +++ b/Test/dafny0/Basics.dfy @@ -110,7 +110,7 @@ method TestMulti(m: Multi, p: Multi) assert p.x == 300;
if (*) {
p.x, m.y := 10, 10;
- p.x, m.x := 8, 8; // error: duplicate assignment (since m and p may be the same)
+ p.x, m.x := 8, 8;
}
var a, b := new int[20], new int[30];
@@ -184,4 +184,59 @@ method EuclideanTest(a: int, b: int) assert 0 <= r < abs(b);
assert a == b * q + r;
assert (a/b) * b + a % b == a;
-}
\ No newline at end of file +}
+
+method havocInMultiassignment()
+{
+ var i: nat, j: nat;
+ i, j := *, 3;
+ assert 0 <= i;
+}
+
+method m()
+{
+ var i: int, j: int;
+ i, j := 3, 6;
+ i, i := 3, 3;
+}
+
+method swap(a: array<int>, i: nat, j: nat)
+ requires a != null && 0 <= i < a.Length && 0 <= j < a.Length;
+ modifies a;
+{
+ a[i], a[j] := a[j], a[i];
+}
+
+class CC {
+ var x : int;
+ var y : int;
+}
+
+method notQuiteSwap(c: CC, d: CC)
+ requires c != null && d != null;
+ modifies c,d;
+{
+ c.x, d.x := c.x, c.x;
+}
+
+method notQuiteSwap2(c: CC, d: CC)
+ requires c != null && d != null;
+ modifies c,d;
+{
+ c.x, d.x := d.x, c.y; // BAD: c and d could be the same.
+}
+
+method OKNowIt'sSwapAgain(c: CC, d: CC)
+ requires c != null && d != null;
+ modifies c,d;
+{
+ c.x, d.x := d.x, c.x;
+}
+
+method notQuiteSwap3(c: CC, d: CC)
+ requires c != null && d != null && c != d;
+ modifies c,d;
+{
+ c.x, d.x := 4, c.y;
+ c.x, c.y := 3, c.y;
+}
diff --git a/Test/dafny0/LiberalEquality.dfy b/Test/dafny0/LiberalEquality.dfy new file mode 100644 index 00000000..3dc52c80 --- /dev/null +++ b/Test/dafny0/LiberalEquality.dfy @@ -0,0 +1,55 @@ +
+class Array<T>
+{
+ var Length: nat;
+}
+
+class Test<T> {
+ var a: Array<int>;
+ var b: Array<T>;
+ predicate valid()
+ reads this, a, b;
+ {
+ a != null && b != null && a != b && a.Length == b.Length
+ }
+}
+
+method m1<T, U>(t: T, u: U)
+ requires t != u;
+{
+
+}
+
+method m2<T>(t: array<T>, a: array<int>)
+ requires t != null && a != null && t != a && t.Length == a.Length;
+{
+
+}
+
+
+class Weird<T, U, V>
+{
+
+}
+
+
+method m3<T, V>(a: Weird<T, int, V>, b: Weird<T, bool, V>)
+ requires a == b; // Bad: second parameter can't be both bool and int.
+{
+
+}
+
+
+method m4<T, U, V>(a: Weird<T, U, V>, b: Weird<T, bool, V>)
+ requires a == b;
+{
+
+}
+
+
+// Just to make sure nothing went wrong.
+method m5(a: array<int>, b: array<bool>)
+ requires a == b; // Bad: never equal
+{
+
+}
diff --git a/Test/dafny0/Modules0.dfy b/Test/dafny0/Modules0.dfy index b171a9c9..cc66c3c1 100644 --- a/Test/dafny0/Modules0.dfy +++ b/Test/dafny0/Modules0.dfy @@ -301,3 +301,31 @@ module Local imports NonLocalA, NonLocalB { method Q() { }
}
}
+
+// ------ qualified type names ----------------------------------
+
+module Q_Imp {
+ class Node { }
+ datatype List<T> = Nil | Cons(T, List);
+ class Klassy {
+ method Init()
+ }
+}
+
+module Q_M imports Q_Imp {
+ method MyMethod(root: Q_Imp.Node, S: set<Node>)
+ requires root in S; // error: the element type of S does not agree with the type of root
+ {
+ var i := new Q_Imp.Node;
+ var j := new Node;
+ assert i != j; // error: i and j have different types
+ var k: LongLostModule.Node; // error: undeclared module
+ var l: Wazzup.WazzupA; // error: undeclared module (it has not been imported)
+ var m: Q_Imp.Edon; // error: undeclared class in module Q_Imp
+ var n: Q_Imp.List;
+ var o := new Q_Imp.List; // error: not a class declared in module Q_Imp
+ var p := new Q_Imp.Klassy.Create(); // error: Create is not a method
+ var q := new Q_Imp.Klassy.Init();
+ }
+ class Node { }
+}
diff --git a/Test/dafny0/Modules1.dfy b/Test/dafny0/Modules1.dfy index 5e2d0fff..e8a88749 100644 --- a/Test/dafny0/Modules1.dfy +++ b/Test/dafny0/Modules1.dfy @@ -89,3 +89,23 @@ module B_Visibility imports A_Visibility { }
}
}
+
+// ------ qualified type names ----------------------------------
+
+module Q_Imp {
+ class Node { }
+ class Klassy {
+ method Init()
+ }
+}
+
+module Q_M imports Q_Imp {
+ method MyMethod(root: Q_Imp.Node, S: set<Q_Imp.Node>)
+ requires root in S;
+ {
+ var i := new Q_Imp.Node;
+ var j := new Node;
+ assert i != j; // fine
+ var q := new Q_Imp.Klassy.Init();
+ }
+}
diff --git a/Test/dafny0/ParallelResolveErrors.dfy b/Test/dafny0/ParallelResolveErrors.dfy index ab711d02..f260edb5 100644 --- a/Test/dafny0/ParallelResolveErrors.dfy +++ b/Test/dafny0/ParallelResolveErrors.dfy @@ -103,6 +103,6 @@ method M1() { method M2() {
var a := new int[100];
parallel (x | 0 <= x < 100) {
- a[x] :| a[x] > 0; // error: not allowed to update heap location in a parallel statement with a(n implicit) assume
+ a[x] :| assume a[x] > 0; // error: not allowed to update heap location in a parallel statement with an assume
}
}
diff --git a/Test/dafny0/Predicates.dfy b/Test/dafny0/Predicates.dfy index f8569b3a..146129b5 100644 --- a/Test/dafny0/Predicates.dfy +++ b/Test/dafny0/Predicates.dfy @@ -79,7 +79,7 @@ module Tight refines Loose { }
module UnawareClient imports Loose {
- method Main() {
+ method Main0() {
var n := new MyNumber.Init();
assert n.N == 0; // error: this is not known
n.Inc();
@@ -90,7 +90,7 @@ module UnawareClient imports Loose { }
module AwareClient imports Tight {
- method Main() {
+ method Main1() {
var n := new MyNumber.Init();
assert n.N == 0;
n.Inc();
diff --git a/Test/dafny0/SmallTests.dfy b/Test/dafny0/SmallTests.dfy index 4d219cd3..e8b618d7 100644 --- a/Test/dafny0/SmallTests.dfy +++ b/Test/dafny0/SmallTests.dfy @@ -542,21 +542,21 @@ method AssignSuchThat0(a: int, b: int) returns (x: int, y: int) ensures x == a && y == b;
{
if (*) {
- x, y :| a <= x < a + 1 && b + a <= y + a && y <= b;
+ x, y :| assume a <= x < a + 1 && b + a <= y + a && y <= b;
} else {
- var xx, yy :| a <= xx < a + 1 && b + a <= yy + a && yy <= b;
+ var xx, yy :| assume a <= xx < a + 1 && b + a <= yy + a && yy <= b;
x, y := xx, yy;
}
}
method AssignSuchThat1(a: int, b: int) returns (x: int, y: int)
{
- var k :| 0 <= k < a - b; // this acts like an 'assume 0 < a - b;'
+ var k :| assume 0 <= k < a - b; // this acts like an 'assume 0 < a - b;'
assert b < a;
- k :| k == old(2*k); // note, the 'old' has no effect on local variables like k
+ k :| assume k == old(2*k); // note, the 'old' has no effect on local variables like k
assert k == 0;
var S := {2, 4, 7};
- var T :| T <= S;
+ var T :| assume T <= S;
assert 3 !in T;
assert T == {}; // error: T may be larger
}
@@ -568,38 +568,38 @@ method AssignSuchThat2(i: int, j: int, ghost S: set<Node>) var a := new int[25];
var t;
if (0 <= i < j < 25) {
- a[i], t, a[j], n.next, n :| true;
+ a[i], t, a[j], n.next, n :| assume true;
}
if (n != null && n.next != null) {
assume n in S && n.next in S;
- n.next.next, n.next :| n != null && n.next != null && n.next.next == n.next; // error: n.next may equal n (thus aliasing n.next.next and n.next)
+ n.next.next, n.next :| assume n != null && n.next != null && n.next.next == n.next; // error: n.next may equal n (thus aliasing n.next.next and n.next)
} else if (0 <= i < 25 && 0 <= j < 25) {
- t, a[i], a[j] :| t < a[i] < a[j]; // error: i may equal j (thus aliasing a[i] and a[j])
+ t, a[i], a[j] :| assume t < a[i] < a[j]; // error: i may equal j (thus aliasing a[i] and a[j])
}
}
method AssignSuchThat3()
{
var n := new Node;
- n, n.next :| n.next == n; // error: RHS is not well defined (RHS is evaluated after the havocking of the LHS)
+ n, n.next :| assume n.next == n; // error: RHS is not well defined (RHS is evaluated after the havocking of the LHS)
}
method AssignSuchThat4()
{
var n := new Node;
- n, n.next :| n != null && n.next == n; // that's the ticket
+ n, n.next :| assume n != null && n.next == n; // that's the ticket
}
method AssignSuchThat5()
{
var n := new Node;
- n :| fresh(n); // fine
+ n :| assume fresh(n); // fine
assert false; // error
}
method AssignSuchThat6()
{
var n: Node;
- n :| n != null && fresh(n); // there is no non-null fresh object, so this amounts to 'assume false;'
+ n :| assume n != null && fresh(n); // there is no non-null fresh object, so this amounts to 'assume false;'
assert false; // no problemo
}
diff --git a/Test/dafny0/TypeTests.dfy b/Test/dafny0/TypeTests.dfy index 29274381..8434f06c 100644 --- a/Test/dafny0/TypeTests.dfy +++ b/Test/dafny0/TypeTests.dfy @@ -92,3 +92,28 @@ method K(s: set<nat>) { // error: not allowed to instantiate 'set' with 'nat' var b := new nat[100,200]; // error: not allowed the type array2<nat>
}
+// --------------------- more ghost tests, for assign-such-that statements
+
+method M()
+{
+ ghost var b: bool;
+ ghost var k: int, l: int;
+ var m: int;
+
+ // These three statements are allowed by the resolver, but the compiler will complain
+ // if it ever gets them.
+ k :| k < 10;
+ k, m :| 0 <= k < m;
+ m :| m < 10;
+
+ // Because of the ghost guard, these 'if' statements are ghost contexts, so only
+ // assignments to ghosts are allowed.
+ if (b) {
+ k :| k < 10; // should be allowed
+ k, l :| 0 <= k < l; // ditto
+ }
+ if (b) {
+ m :| m < 10; // error: not allowed in ghost context
+ k, m :| 0 <= k < m; // error: not allowed in ghost context
+ }
+}
diff --git a/Test/dafny0/runtest.bat b/Test/dafny0/runtest.bat index e4c134f6..ac7c8aed 100644 --- a/Test/dafny0/runtest.bat +++ b/Test/dafny0/runtest.bat @@ -3,7 +3,6 @@ setlocal set BOOGIEDIR=..\..\Binaries
set DAFNY_EXE=%BOOGIEDIR%\Dafny.exe
-set BPLEXE=%BOOGIEDIR%\Boogie.exe
for %%f in (Simple.dfy) do (
echo.
@@ -22,7 +21,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 Skeletons.dfy Maps.dfy) do (
+ Predicates.dfy Skeletons.dfy Maps.dfy LiberalEquality.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 9ed6d75a..7c7719ee 100644 --- a/Test/dafny1/Answer +++ b/Test/dafny1/Answer @@ -1,8 +1,4 @@ --------------------- BQueue.bpl --------------------
-
-Boogie program verifier finished with 8 verified, 0 errors
-
-------------------- Queue.dfy --------------------
Dafny program verifier finished with 22 verified, 0 errors
diff --git a/Test/dafny1/runtest.bat b/Test/dafny1/runtest.bat index 1f5d78df..d098d753 100644 --- a/Test/dafny1/runtest.bat +++ b/Test/dafny1/runtest.bat @@ -3,14 +3,6 @@ setlocal set BOOGIEDIR=..\..\Binaries
set DAFNY_EXE=%BOOGIEDIR%\Dafny.exe
-set BPLEXE=%BOOGIEDIR%\Boogie.exe
-set CSC=c:/Windows/Microsoft.NET/Framework/v4.0.30319/csc.exe
-
-for %%f in (BQueue.bpl) do (
- echo.
- echo -------------------- %%f --------------------
- %BPLEXE% %* %%f
-)
for %%f in (Queue.dfy PriorityQueue.dfy
ExtensibleArray.dfy ExtensibleArrayAuto.dfy
diff --git a/Test/dafny2/Answer b/Test/dafny2/Answer index 381b9cb1..9c37549e 100644 --- a/Test/dafny2/Answer +++ b/Test/dafny2/Answer @@ -31,6 +31,22 @@ Dafny program verifier finished with 23 verified, 0 errors Dafny program verifier finished with 5 verified, 0 errors
+-------------------- TreeFill.dfy --------------------
+
+Dafny program verifier finished with 3 verified, 0 errors
+
+-------------------- TuringFactorial.dfy --------------------
+
+Dafny program verifier finished with 3 verified, 0 errors
+
-------------------- StoreAndRetrieve.dfy --------------------
Dafny program verifier finished with 22 verified, 0 errors
+
+-------------------- MajorityVote.dfy --------------------
+
+Dafny program verifier finished with 11 verified, 0 errors
+
+-------------------- SegmentSum.dfy --------------------
+
+Dafny program verifier finished with 3 verified, 0 errors
diff --git a/Test/dafny2/MajorityVote.dfy b/Test/dafny2/MajorityVote.dfy new file mode 100644 index 00000000..a7512486 --- /dev/null +++ b/Test/dafny2/MajorityVote.dfy @@ -0,0 +1,171 @@ +// Rustan Leino, June 2012.
+// This file verifies an algorithm, due to Boyer and Moore, that finds the majority choice
+// among a sequence of votes, see http://www.cs.utexas.edu/~moore/best-ideas/mjrty/.
+// Actually, this algorithm is a slight variation on theirs, but the general idea for why
+// it is correct is the same. In the Boyer and Moore algorithm, the loop counter is advanced
+// by exactly 1 each iteration, which means that there may or may not be a "current leader".
+// In my program below, I had instead written the loop invariant to say there is always a
+// "current leader", which requires the loop index sometimes to skip a value.
+//
+// This file has two versions of the algorithm. In the first version, the given sequence
+// of votes is assumed to have a (strict) majority choice, meaning that strictly more than
+// 50% of the votes are for one candidate. It is convenient to have a name for the majority
+// choice, in order to talk about it in specifications. The easiest way to do this in
+// Dafny is probably to introduce a ghost parameter with the given properties. That's what
+// the algorithm does, see parameter K. The postcondition is thus to output the value of
+// K, which is done in the non-ghost out-parameter k.
+// The proof of the algorithm requires two lemmas. These lemmas are proved automatically
+// by Dafny's induction tactic.
+//
+// In the second version of the program, the main method does not assume there is a majority
+// choice. Rather, it eseentially uses the first algorithm and then checks if what it
+// returns really is a majority choice. To do this, the specification of the first algorithm
+// needs to be changed slightly to accommodate the possibility that there is no majority
+// choice. That change in specification is also reflected in the loop invariant. Moreover,
+// the algorithm itself now needs to extra 'if' statements to see if the entire sequence
+// has been searched through. (This extra 'if' is essentially already handled by Boyer and
+// Moore's algorithm, because it increments the loop index by 1 each iteration and therefore
+// already has a special case for the case of running out of sequence elements without a
+// current leader.)
+// The calling harness, DetermineElection, somewhat existentially comes up with the majority
+// choice, if there is such a choice, and then passes in that choice as the ghost parameter K
+// to the main algorithm. Neat, huh?
+
+// Advanced remark:
+// There is a subtle situation in the verification of DetermineElection. Suppose the type
+// parameter Candidate denotes some type whose instances depend on which object are
+// allocated. For example, if Candidate is some class type, then more candidates can come
+// into being by object allocations (using "new"). What does the quantification of
+// candidates "c" in the postcondition of DetermineElection now mean--all candidates that
+// existed in the pre-state or (the possibly larger set of) all candidates that exist in the
+// post-state? (It means the latter.) And if there does not exist a candidate in majority
+// in the pre-state, could there be a (newly created) candidate in majority in the post-state?
+// This will require some proof. The simplest argument seems to be that even if more candidates
+// are created during the course of DetermineElection, such candidates cannot possibly
+// be in majority in the sequence "a", since "a" can only contain candidates that were already
+// created in the pre-state. This property is easily specified by adding a postcondition
+// to the Count function. Alternatively, one could have added the antecedent "c in a" or
+// "old(allocated(c))" to the "forall c" quantification in the postcondition of DetermineElection.
+
+function method Count<T>(a: seq<T>, s: int, t: int, x: T): int
+ requires 0 <= s <= t <= |a|;
+ ensures Count(a, s, t, x) == 0 || x in a;
+{
+ if s == t then 0 else
+ Count(a, s, t-1, x) + if a[t-1] == x then 1 else 0
+}
+
+// Here is the first version of the algorithm, the one that assumes there is a majority choice.
+
+method FindWinner<Candidate>(a: seq<Candidate>, ghost K: Candidate) returns (k: Candidate)
+ requires 2 * Count(a, 0, |a|, K) > |a|; // K has a (strict) majority of the votes
+ ensures k == K; // find K
+{
+ k := a[0];
+ var n, c, s := 1, 1, 0;
+ while (n < |a|)
+ invariant 0 <= s <= n <= |a|;
+ invariant 2 * Count(a, s, |a|, K) > |a| - s; // K has majority among a[s..]
+ invariant 2 * Count(a, s, n, k) > n - s; // k has majority among a[s..n]
+ invariant c == Count(a, s, n, k);
+ {
+ if (a[n] == k) {
+ n, c := n + 1, c + 1;
+ } else if (2 * c > n + 1 - s) {
+ n := n + 1;
+ } else {
+ n := n + 1;
+ // We have 2*Count(a, s, n, k) == n-s, and thus the following lemma
+ // lets us conclude 2*Count(a, s, n, K) <= n-s.
+ Lemma_Unique(a, s, n, K, k);
+ // We also have 2*Count(a, s, |a|, K) > |a|-s, and the following lemma
+ // tells us Count(a, s, |a|, K) == Count(a, s, n, K) + Count(a, n, |a|, K),
+ // and thus we can conclude 2*Count(a, n, |a|, K) > |a|-n.
+ Lemma_Split(a, s, n, |a|, K);
+ k, n, c, s := a[n], n + 1, 1, n;
+ }
+ }
+ Lemma_Unique(a, s, |a|, K, k); // both k and K have a majority, so K == k
+}
+
+// ------------------------------------------------------------------------------
+
+// Here is the second version of the program, the one that also computes whether or not
+// there is a majority choice.
+
+method DetermineElection<Candidate>(a: seq<Candidate>) returns (hasWinner: bool, cand: Candidate)
+ ensures hasWinner ==> 2 * Count(a, 0, |a|, cand) > |a|;
+ ensures !hasWinner ==> forall c :: 2 * Count(a, 0, |a|, c) <= |a|;
+{
+ ghost var b := exists c :: 2 * Count(a, 0, |a|, c) > |a|;
+ ghost var w :| b ==> 2 * Count(a, 0, |a|, w) > |a|;
+ cand := SearchForWinner(a, b, w);
+ return 2 * Count(a, 0, |a|, cand) > |a|, cand;
+}
+
+// The difference between SearchForWinner for FindWinner above are the occurrences of the
+// antecedent "hasWinner ==>" and the two checks for no-more-votes that may result in a "return"
+// statement.
+
+method SearchForWinner<Candidate>(a: seq<Candidate>, ghost hasWinner: bool, ghost K: Candidate) returns (k: Candidate)
+ requires hasWinner ==> 2 * Count(a, 0, |a|, K) > |a|; // K has a (strict) majority of the votes
+ ensures hasWinner ==> k == K; // find K
+{
+ if (|a| == 0) { return; }
+ k := a[0];
+ var n, c, s := 1, 1, 0;
+ while (n < |a|)
+ invariant 0 <= s <= n <= |a|;
+ invariant hasWinner ==> 2 * Count(a, s, |a|, K) > |a| - s; // K has majority among a[s..]
+ invariant 2 * Count(a, s, n, k) > n - s; // k has majority among a[s..n]
+ invariant c == Count(a, s, n, k);
+ {
+ if (a[n] == k) {
+ n, c := n + 1, c + 1;
+ } else if (2 * c > n + 1 - s) {
+ n := n + 1;
+ } else {
+ n := n + 1;
+ // We have 2*Count(a, s, n, k) == n-s, and thus the following lemma
+ // lets us conclude 2*Count(a, s, n, K) <= n-s.
+ Lemma_Unique(a, s, n, K, k);
+ // We also have 2*Count(a, s, |a|, K) > |a|-s, and the following lemma
+ // tells us Count(a, s, |a|, K) == Count(a, s, n, K) + Count(a, n, |a|, K),
+ // and thus we can conclude 2*Count(a, n, |a|, K) > |a|-n.
+ Lemma_Split(a, s, n, |a|, K);
+ if (|a| == n) { return; }
+ k, n, c, s := a[n], n + 1, 1, n;
+ }
+ }
+ Lemma_Unique(a, s, |a|, K, k); // both k and K have a majority, so K == k
+}
+
+// ------------------------------------------------------------------------------
+
+// Here are two lemmas about Count that are used in the methods above.
+
+ghost method Lemma_Split<T>(a: seq<T>, s: int, t: int, u: int, x: T)
+ requires 0 <= s <= t <= u <= |a|;
+ ensures Count(a, s, t, x) + Count(a, t, u, x) == Count(a, s, u, x);
+{
+ /* The postcondition of this method is proved automatically via Dafny's
+ induction tactic. But if a manual proof had to be provided, it would
+ look like this:
+ if (s != t) {
+ Lemma_Split(a, s, t-1, u, x);
+ }
+ */
+}
+
+ghost method Lemma_Unique<T>(a: seq<T>, s: int, t: int, x: T, y: T)
+ requires 0 <= s <= t <= |a|;
+ ensures x != y ==> Count(a, s, t, x) + Count(a, s, t, y) <= t - s;
+{
+ /* The postcondition of this method is proved automatically via Dafny's
+ induction tactic. But if a manual proof had to be provided, it would
+ look like this:
+ if (s != t) {
+ Lemma_Unique(a, s, t-1, x, y);
+ }
+ */
+}
diff --git a/Test/dafny2/SegmentSum.dfy b/Test/dafny2/SegmentSum.dfy new file mode 100644 index 00000000..dc67162b --- /dev/null +++ b/Test/dafny2/SegmentSum.dfy @@ -0,0 +1,29 @@ +function Sum(a: seq<int>, s: int, t: int): int
+ requires 0 <= s <= t <= |a|;
+{
+ if s == t then 0 else Sum(a, s, t-1) + a[t-1]
+}
+
+method MaxSegSum(a: seq<int>) returns (k: int, m: int)
+ ensures 0 <= k <= m <= |a|;
+ ensures forall p,q :: 0 <= p <= q <= |a| ==> Sum(a, p, q) <= Sum(a, k, m);
+{
+ k, m := 0, 0;
+ var s := 0; // invariant s == Sum(a, k, m)
+ var n := 0;
+ var c, t := 0, 0; // invariant t == Sum(a, c, n)
+ while (n < |a|)
+ invariant n <= |a|;
+ invariant 0 <= c <= n && t == Sum(a, c, n);
+ invariant forall b :: 0 <= b <= n ==> Sum(a, b, n) <= Sum(a, c, n);
+ invariant 0 <= k <= m <= n && s == Sum(a, k, m);
+ invariant forall p,q :: 0 <= p <= q <= n ==> Sum(a, p, q) <= Sum(a, k, m);
+ {
+ t, n := t + a[n], n + 1;
+ if (t < 0) {
+ c, t := n, 0;
+ } else if (s < t) {
+ k, m, s := c, n, t;
+ }
+ }
+}
diff --git a/Test/dafny2/StoreAndRetrieve.dfy b/Test/dafny2/StoreAndRetrieve.dfy index ea26a234..15c82d65 100644 --- a/Test/dafny2/StoreAndRetrieve.dfy +++ b/Test/dafny2/StoreAndRetrieve.dfy @@ -1,4 +1,4 @@ -module A imports Library {
+ghost module A imports Library {
class {:autocontracts} StoreAndRetrieve<Thing> {
ghost var Contents: set<Thing>;
predicate Valid
diff --git a/Test/dafny2/TreeFill.dfy b/Test/dafny2/TreeFill.dfy new file mode 100644 index 00000000..f7e2cc89 --- /dev/null +++ b/Test/dafny2/TreeFill.dfy @@ -0,0 +1,27 @@ +datatype Tree<T> = Null | Node(Tree, T, Tree);
+
+function Contains<T>(t: Tree, v: T): bool
+{
+ match t
+ case Null => false
+ case Node(left, x, right) => x == v || Contains(left, v) || Contains(right, v)
+}
+
+method Fill<T>(t: Tree, a: array<T>, start: int) returns (end: int)
+ requires a != null && 0 <= start <= a.Length;
+ modifies a;
+ ensures start <= end <= a.Length;
+ ensures forall i :: 0 <= i < start ==> a[i] == old(a[i]);
+ ensures forall i :: start <= i < end ==> Contains(t, a[i]);
+{
+ match (t) {
+ case Null =>
+ end := start;
+ case Node(left, x, right) =>
+ end := Fill(left, a, start);
+ if (end < a.Length) {
+ a[end] := x;
+ end := Fill(right, a, end + 1);
+ }
+ }
+}
diff --git a/Test/dafny2/TuringFactorial.dfy b/Test/dafny2/TuringFactorial.dfy new file mode 100644 index 00000000..585c998e --- /dev/null +++ b/Test/dafny2/TuringFactorial.dfy @@ -0,0 +1,26 @@ +function Factorial(n: nat): nat
+{
+ if n == 0 then 1 else n * Factorial(n-1)
+}
+
+method ComputeFactorial(n: int) returns (u: int)
+ requires 1 <= n;
+ ensures u == Factorial(n);
+{
+ var r := 1;
+ u := 1;
+ while (r < n)
+ invariant r <= n;
+ invariant u == Factorial(r);
+ {
+ var v, s := u, 1;
+ while (s < r + 1)
+ invariant s <= r + 1;
+ invariant v == Factorial(r) && u == s * Factorial(r);
+ {
+ u := u + v;
+ s := s + 1;
+ }
+ r := r + 1;
+ }
+}
diff --git a/Test/dafny2/runtest.bat b/Test/dafny2/runtest.bat index a4796939..b68ba251 100644 --- a/Test/dafny2/runtest.bat +++ b/Test/dafny2/runtest.bat @@ -3,7 +3,6 @@ setlocal set BOOGIEDIR=..\..\Binaries
set DAFNY_EXE=%BOOGIEDIR%\Dafny.exe
-set CSC=c:/Windows/Microsoft.NET/Framework/v4.0.30319/csc.exe
REM soon again: SnapshotableTrees.dfy
for %%f in (
@@ -14,8 +13,8 @@ for %%f in ( COST-verif-comp-2011-2-MaxTree-datatype.dfy
COST-verif-comp-2011-3-TwoDuplicates.dfy
COST-verif-comp-2011-4-FloydCycleDetect.dfy
- Intervals.dfy
- StoreAndRetrieve.dfy
+ Intervals.dfy TreeFill.dfy TuringFactorial.dfy
+ StoreAndRetrieve.dfy MajorityVote.dfy SegmentSum.dfy
) do (
echo.
echo -------------------- %%f --------------------
diff --git a/Test/dafnyRuntimeChecking/Answer b/Test/dafnyRuntimeChecking/Answer index 6bda12af..0cc946ab 100644 --- a/Test/dafnyRuntimeChecking/Answer +++ b/Test/dafnyRuntimeChecking/Answer @@ -7,10 +7,11 @@ Rewrote assembly into AssumeStmt0.exe using System.Diagnostics.Contracts;
using System.Numerics;
-using System.Collections.Generic;
namespace Dafny
{
+ using System.Collections.Generic;
+
public class Set<T>
{
Dictionary<T, bool> dict;
@@ -589,13 +590,13 @@ namespace Dafny { }
}
-public class @_default {
+public class @__default {
public void @Main()
{
Contract.Assume((new BigInteger(2)) < (new BigInteger(10)));
}
public static void Main(string[] args) {
- @_default b = new @_default();
+ @__default b = new @__default();
b.Main();
}
}
@@ -608,10 +609,11 @@ Rewrote assembly into AssumeStmt1.exe using System.Diagnostics.Contracts;
using System.Numerics;
-using System.Collections.Generic;
namespace Dafny
{
+ using System.Collections.Generic;
+
public class Set<T>
{
Dictionary<T, bool> dict;
@@ -1190,13 +1192,13 @@ namespace Dafny { }
}
-public class @_default {
+public class @__default {
public void @Main()
{
Contract.Assume((new BigInteger(10)) < (new BigInteger(2)));
}
public static void Main(string[] args) {
- @_default b = new @_default();
+ @__default b = new @__default();
b.Main();
}
}
@@ -1209,10 +1211,11 @@ Rewrote assembly into AssertStmt0.exe using System.Diagnostics.Contracts;
using System.Numerics;
-using System.Collections.Generic;
namespace Dafny
{
+ using System.Collections.Generic;
+
public class Set<T>
{
Dictionary<T, bool> dict;
@@ -1791,13 +1794,13 @@ namespace Dafny { }
}
-public class @_default {
+public class @__default {
public void @Main()
{
Contract.Assert((new BigInteger(2)) < (new BigInteger(10)));
}
public static void Main(string[] args) {
- @_default b = new @_default();
+ @__default b = new @__default();
b.Main();
}
}
@@ -1810,10 +1813,11 @@ Rewrote assembly into AssertStmt1.exe using System.Diagnostics.Contracts;
using System.Numerics;
-using System.Collections.Generic;
namespace Dafny
{
+ using System.Collections.Generic;
+
public class Set<T>
{
Dictionary<T, bool> dict;
@@ -2392,13 +2396,13 @@ namespace Dafny { }
}
-public class @_default {
+public class @__default {
public void @Main()
{
Contract.Assert((new BigInteger(10)) < (new BigInteger(2)));
}
public static void Main(string[] args) {
- @_default b = new @_default();
+ @__default b = new @__default();
b.Main();
}
}
@@ -2411,10 +2415,11 @@ Rewrote assembly into Precondition0.exe using System.Diagnostics.Contracts;
using System.Numerics;
-using System.Collections.Generic;
namespace Dafny
{
+ using System.Collections.Generic;
+
public class Set<T>
{
Dictionary<T, bool> dict;
@@ -2993,13 +2998,13 @@ namespace Dafny { }
}
-public class @_default {
+public class @__default {
public void @Main()
{
Contract.Requires(true);
}
public static void Main(string[] args) {
- @_default b = new @_default();
+ @__default b = new @__default();
b.Main();
}
}
@@ -3012,10 +3017,11 @@ Rewrote assembly into Precondition1.exe using System.Diagnostics.Contracts;
using System.Numerics;
-using System.Collections.Generic;
namespace Dafny
{
+ using System.Collections.Generic;
+
public class Set<T>
{
Dictionary<T, bool> dict;
@@ -3594,7 +3600,7 @@ namespace Dafny { }
}
-public class @_default {
+public class @__default {
public void @foo(BigInteger @x, BigInteger @y)
{
Contract.Requires((new BigInteger(0)) <= (@x));
@@ -3605,7 +3611,7 @@ public class @_default { (this).@foo(new BigInteger(2), (new BigInteger(0)) - (new BigInteger(7)));
}
public static void Main(string[] args) {
- @_default b = new @_default();
+ @__default b = new @__default();
b.Main();
}
}
@@ -3618,10 +3624,11 @@ Rewrote assembly into Postcondition0.exe using System.Diagnostics.Contracts;
using System.Numerics;
-using System.Collections.Generic;
namespace Dafny
{
+ using System.Collections.Generic;
+
public class Set<T>
{
Dictionary<T, bool> dict;
@@ -4200,13 +4207,13 @@ namespace Dafny { }
}
-public class @_default {
+public class @__default {
public void @Main()
{
Contract.Ensures(true);
}
public static void Main(string[] args) {
- @_default b = new @_default();
+ @__default b = new @__default();
b.Main();
}
}
@@ -4219,10 +4226,11 @@ Rewrote assembly into Postcondition1.exe using System.Diagnostics.Contracts;
using System.Numerics;
-using System.Collections.Generic;
namespace Dafny
{
+ using System.Collections.Generic;
+
public class Set<T>
{
Dictionary<T, bool> dict;
@@ -4801,7 +4809,7 @@ namespace Dafny { }
}
-public class @_default {
+public class @__default {
public BigInteger @x = new BigInteger(0);
public BigInteger @y = new BigInteger(0);
public void @Main()
@@ -4812,7 +4820,7 @@ public class @_default { (this).@y = (new BigInteger(0)) - (new BigInteger(7));
}
public static void Main(string[] args) {
- @_default b = new @_default();
+ @__default b = new @__default();
b.Main();
}
}
diff --git a/Test/dafnytests.txt b/Test/dafnytests.txt index 74f055ab..ca40465e 100644 --- a/Test/dafnytests.txt +++ b/Test/dafnytests.txt @@ -2,7 +2,7 @@ dafny0 Use Dafny functionality tests dafny1 Use Various Dafny examples
dafny2 Use More Dafny examples
dafnyRuntimeChecking Use Dafny runtime checking tests
-dafnyCompiler Use Dafny compiler tests
+dafnyCompiler Postpone Dafny compiler tests
VSI-Benchmarks Use Solutions to Verified Software Initiative verification challenges
vacid0 Use Dafny attempts to VACID Edition 0 benchmarks
vstte2012 Use Dafny solutions for the VSTTE 2012 program verification competition
diff --git a/Test/test15/Answer b/Test/test15/Answer index 56c247c2..04a94759 100644 --- a/Test/test15/Answer +++ b/Test/test15/Answer @@ -144,7 +144,7 @@ type -> { T@U!val!0 -> T@T!val!4
T@U!val!1 -> T@T!val!2
T@U!val!2 -> T@T!val!3
- T@U!val!3 -> T@T!val!0
+ -2 -> T@T!val!0
else -> T@T!val!4
}
Ctor -> {
@@ -162,12 +162,12 @@ Ctor -> { 6 5 -> true
else -> true
}
-MapType0Select -> {
- T@U!val!0 T@U!val!1 T@U!val!2 -> T@U!val!3
- else -> T@U!val!3
+[3] -> {
+ T@U!val!0 T@U!val!1 T@U!val!2 -> -2
+ else -> -2
}
U_2_int -> {
- T@U!val!3 -> -2
+ -2 -> -2
else -> -2
}
MapType0TypeInv1 -> {
@@ -187,8 +187,8 @@ MapType0TypeInv0 -> { else -> T@T!val!2
}
int_2_U -> {
- -2 -> T@U!val!3
- else -> T@U!val!3
+ -2 -> -2
+ else -> -2
}
*** STATE <initial>
Heap -> T@U!val!0
diff --git a/Test/textbook/Answer b/Test/textbook/Answer index dace3eb3..42e41c5a 100644 --- a/Test/textbook/Answer +++ b/Test/textbook/Answer @@ -22,3 +22,7 @@ Boogie program verifier finished with 1 verified, 0 errors ------------------------------ TuringFactorial.bpl ---------------------
Boogie program verifier finished with 1 verified, 0 errors
+
+------------------------------ BQueue.bpl ---------------------
+
+Boogie program verifier finished with 8 verified, 0 errors
diff --git a/Test/dafny1/BQueue.bpl b/Test/textbook/BQueue.bpl index 77f1efb3..77f1efb3 100644 --- a/Test/dafny1/BQueue.bpl +++ b/Test/textbook/BQueue.bpl diff --git a/Test/textbook/runtest.bat b/Test/textbook/runtest.bat index b747312d..f43e54d9 100644 --- a/Test/textbook/runtest.bat +++ b/Test/textbook/runtest.bat @@ -7,7 +7,7 @@ REM ====================== REM ====================== Examples written in Boogie
REM ======================
for %%f in (Find.bpl DutchFlag.bpl Bubble.bpl DivMod.bpl McCarthy-91.bpl
- TuringFactorial.bpl) do (
+ TuringFactorial.bpl BQueue.bpl) do (
echo.
echo ------------------------------ %%f ---------------------
%BPLEXE% %* %%f
diff --git a/Test/vacid0/LazyInitArray.dfy b/Test/vacid0/LazyInitArray.dfy index e56a8317..3e5a95ef 100644 --- a/Test/vacid0/LazyInitArray.dfy +++ b/Test/vacid0/LazyInitArray.dfy @@ -11,10 +11,10 @@ class LazyInitArray<T> { reads this, a, b, c;
{
a != null && b != null && c != null &&
- a.Length == |Contents| + 1 && // TODO: remove the "+ 1" hack, which currently serves the purpose of distinguishing 'a' from 'b' and 'c'
+ a.Length == |Contents| &&
b.Length == |Contents| &&
c.Length == |Contents| &&
- b != c &&
+ b != c && a != b && a != c &&
0 <= n && n <= c.Length &&
(forall i :: 0 <= i && i < |Contents| ==>
Contents[i] == (if 0 <= b[i] && b[i] < n && c[b[i]] == i then a[i] else Zero)) &&
@@ -41,7 +41,7 @@ class LazyInitArray<T> { ensures |Contents| == N && Zero == zero;
ensures (forall x :: x in Contents ==> x == zero);
{
- a := new T[N+1];
+ a := new T[N];
b := new int[N];
c := new int[N];
n := 0;
diff --git a/Test/vacid0/runtest.bat b/Test/vacid0/runtest.bat index efe7b3d5..cd047d39 100644 --- a/Test/vacid0/runtest.bat +++ b/Test/vacid0/runtest.bat @@ -3,8 +3,6 @@ setlocal set BOOGIEDIR=..\..\Binaries
set DAFNY_EXE=%BOOGIEDIR%\Dafny.exe
-set BPLEXE=%BOOGIEDIR%\Boogie.exe
-set CSC=c:/Windows/Microsoft.NET/Framework/v4.0.30319/csc.exe
for %%f in (LazyInitArray.dfy SparseArray.dfy Composite.dfy) do (
echo.
diff --git a/Test/vstte2012/runtest.bat b/Test/vstte2012/runtest.bat index 770f41dc..7f7c9b9f 100644 --- a/Test/vstte2012/runtest.bat +++ b/Test/vstte2012/runtest.bat @@ -3,7 +3,6 @@ setlocal set BOOGIEDIR=..\..\Binaries
set DAFNY_EXE=%BOOGIEDIR%\Dafny.exe
-set CSC=c:/Windows/Microsoft.NET/Framework/v4.0.30319/csc.exe
for %%f in (
Two-Way-Sort.dfy
diff --git a/Util/Emacs/dafny-mode.el b/Util/Emacs/dafny-mode.el index f16b09b5..05f06b41 100644 --- a/Util/Emacs/dafny-mode.el +++ b/Util/Emacs/dafny-mode.el @@ -30,7 +30,7 @@ ]\\)*" . font-lock-comment-face)
`(,(dafny-regexp-opt '(
- "class" "datatype" "codatatype" "type" "function" "predicate" "ghost" "var" "method" "constructor" "unlimited"
+ "class" "datatype" "codatatype" "type" "function" "predicate" "ghost" "var" "method" "constructor"
"module" "imports" "static" "refines"
"returns" "requires" "ensures" "modifies" "reads" "free"
"invariant" "decreases"
diff --git a/Util/VS2010/Dafny/DafnyLanguageService/Grammar.cs b/Util/VS2010/Dafny/DafnyLanguageService/Grammar.cs index 635115fb..4244e817 100644 --- a/Util/VS2010/Dafny/DafnyLanguageService/Grammar.cs +++ b/Util/VS2010/Dafny/DafnyLanguageService/Grammar.cs @@ -19,7 +19,7 @@ namespace Demo this.MarkReservedWords( // NOTE: these keywords must also appear once more below
"class", "ghost", "static", "var", "method", "constructor", "datatype", "codatatype", "type",
"assert", "assume", "new", "this", "object", "refines",
- "unlimited", "module", "imports",
+ "module", "imports",
"if", "then", "else", "while", "invariant",
"break", "label", "return", "parallel", "havoc", "print",
"returns", "requires", "ensures", "modifies", "reads", "decreases",
@@ -275,7 +275,6 @@ namespace Demo | "this"
| "object"
| "refines"
- | "unlimited"
| "module"
| "imports"
| "if"
diff --git a/Util/VS2010/DafnyExtension/DafnyExtension/TokenTagger.cs b/Util/VS2010/DafnyExtension/DafnyExtension/TokenTagger.cs index 48faa5ec..d621b1a9 100644 --- a/Util/VS2010/DafnyExtension/DafnyExtension/TokenTagger.cs +++ b/Util/VS2010/DafnyExtension/DafnyExtension/TokenTagger.cs @@ -288,7 +288,6 @@ namespace DafnyLanguage case "this":
case "true":
case "type":
- case "unlimited":
case "var":
case "while":
#endregion
diff --git a/Util/latex/dafny.sty b/Util/latex/dafny.sty index 4126d2f2..051d60f4 100644 --- a/Util/latex/dafny.sty +++ b/Util/latex/dafny.sty @@ -6,7 +6,7 @@ \lstdefinelanguage{dafny}{
morekeywords={class,datatype,codatatype,type,bool,nat,int,object,set,multiset,seq,array,array2,array3,%
- function,predicate,unlimited,
+ function,predicate,
ghost,var,static,refines,
method,constructor,returns,module,imports,in,
requires,modifies,ensures,reads,decreases,free,
diff --git a/_admin/Boogie/aste/summary.log b/_admin/Boogie/aste/summary.log index 81442950..93cdd92c 100644 --- a/_admin/Boogie/aste/summary.log +++ b/_admin/Boogie/aste/summary.log @@ -1,20 +1,20 @@ -# Aste started: 2012-05-30 07:00:05
+# Aste started: 2012-06-08 07:00:06
# Host id: Boogiebox
# Configuration: boogie.cfg
# Task: aste.tasks.boogie.FullBuild
-# [2012-05-30 07:01:49] SpecSharp revision: f992747219c4
-# [2012-05-30 07:01:49] SscBoogie revision: f992747219c4
-# [2012-05-30 07:02:37] Boogie revision: c78721acaf27
-[2012-05-30 07:04:36] C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\devenv.com SpecSharp.sln /Project "Checkin Tests" /Build
+# [2012-06-08 07:02:11] SpecSharp revision: b46b99e00a7e
+# [2012-06-08 07:02:11] SscBoogie revision: b46b99e00a7e
+# [2012-06-08 07:03:22] Boogie revision: 4c147e39859e
+[2012-06-08 07:05:15] 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-05-30 07:06:04] C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\devenv.com Boogie.sln /Rebuild Checked
+[2012-06-08 07:06:42] 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()
D:\Temp\aste\Boogie\Source\Core\OOLongUtil.cs(109,7): warning CS0162: Unreachable code detected
- D:\Temp\aste\Boogie\Source\Core\Absy.cs(748,7): warning CC1036: Detected call to method 'Graphing.Graph`1<Microsoft.Boogie.Block>.TopologicalSort' without [Pure] in contracts of method 'Microsoft.Boogie.Program.GraphFromImpl(Microsoft.Boogie.Implementation)'.
+ D:\Temp\aste\Boogie\Source\Core\Absy.cs(770,7): warning CC1036: Detected call to method 'Graphing.Graph`1<Microsoft.Boogie.Block>.TopologicalSort' without [Pure] in contracts of method 'Microsoft.Boogie.Program.GraphFromImpl(Microsoft.Boogie.Implementation)'.
EXEC : warning CC1079: Type Microsoft.Boogie.Variable implements Microsoft.AbstractInterpretationFramework.IVariable.get_Name by inheriting Microsoft.Boogie.NamedDeclaration.get_Name causing the interface contract to not be checked at runtime. Consider adding a wrapper method.
D:\Temp\aste\Boogie\Source\Core\Parser.cs(116,3): warning CC1032: Method 'Microsoft.Boogie.Parser+BvBounds.Resolve(Microsoft.Boogie.ResolutionContext)' overrides 'Microsoft.Boogie.Absy.Resolve(Microsoft.Boogie.ResolutionContext)', thus cannot add Requires.
D:\Temp\aste\Boogie\Source\Core\Parser.cs(121,5): warning CC1032: Method 'Microsoft.Boogie.Parser+BvBounds.Emit(Microsoft.Boogie.TokenTextWriter,System.Int32,System.Boolean)' overrides 'Microsoft.Boogie.Expr.Emit(Microsoft.Boogie.TokenTextWriter,System.Int32,System.Boolean)', thus cannot add Requires.
@@ -41,5 +41,5 @@ warning CS0162: Unreachable code detected
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-05-30 08:07:19] 0 out of 33 test(s) in D:\Temp\aste\Boogie\Test\alltests.txt failed
-# [2012-05-30 08:08:25] Released nightly of Boogie
+[2012-06-08 08:03:55] 0 out of 33 test(s) in D:\Temp\aste\Boogie\Test\alltests.txt failed
+# [2012-06-08 08:04:37] Released nightly of Boogie
diff --git a/_admin/Chalice/aste/summary.log b/_admin/Chalice/aste/summary.log index ade80273..177c1fc2 100644 --- a/_admin/Chalice/aste/summary.log +++ b/_admin/Chalice/aste/summary.log @@ -1,9 +1,9 @@ -# Aste started: 2012-05-25 09:05:16
+# Aste started: 2012-06-08 09:05:33
# Host id: Boogiebox
# Configuration: chalice.cfg
# Task: aste.tasks.chalice.FullBuild
-# [2012-05-25 09:06:05] Chalice revision: 8d9c6d63a543
-[2012-05-25 09:07:29] cmd /c "(set JAVA_OPTS=-Dsbt.ivy.home=D:\temp\.ivy2\) && (sbt.bat clean compile)"
+# [2012-06-08 09:06:28] Chalice revision: 819624caaac6
+[2012-06-08 09:07:52] cmd /c "(set JAVA_OPTS=-Dsbt.ivy.home=D:\temp\.ivy2\) && (sbt.bat clean compile)"
[warn] D:\temp\aste\Boogie\Chalice\src\main\scala\Ast.scala:77: case class `class SeqClass' has case class ancestor `class Class'. This has been deprecated for unduly complicating both usage and implementation. You should instead use extractors for pattern matching on non-leaf nodes.
[warn] D:\temp\aste\Boogie\Chalice\src\main\scala\Ast.scala:111: case class `class TokenClass' has case class ancestor `class Class'. This has been deprecated for unduly complicating both usage and implementation. You should instead use extractors for pattern matching on non-leaf nodes.
@@ -11,5 +11,13 @@ [warn] D:\temp\aste\Boogie\Chalice\src\main\scala\Ast.scala:141: case class `class TokenType' has case class ancestor `class Type'. This has been deprecated for unduly complicating both usage and implementation. You should instead use extractors for pattern matching on non-leaf nodes.
[warn] D:\temp\aste\Boogie\Chalice\src\main\scala\Ast.scala:168: case class `class SpecialField' has case class ancestor `class Field'. This has been deprecated for unduly complicating both usage and implementation. You should instead use extractors for pattern matching on non-leaf nodes.
[warn] D:\temp\aste\Boogie\Chalice\src\main\scala\Ast.scala:227: case class `class SpecialVariable' has case class ancestor `class Variable'. This has been deprecated for unduly complicating both usage and implementation. You should instead use extractors for pattern matching on non-leaf nodes.
-[2012-05-25 10:22:31] 0 out of 83 test(s) failed
-# [2012-05-25 10:23:12] Released nightly of Chalice
+[2012-06-08 09:42:23] 0 out of 85 test(s) failed
+[2012-06-08 09:43:39] cmd /c "(set JAVA_OPTS=-Dsbt.ivy.home=D:\temp\.ivy2\) && (create_release.bat)"
+
+ [warn] D:\temp\aste\Boogie\Chalice\src\main\scala\Ast.scala:77: case class `class SeqClass' has case class ancestor `class Class'. This has been deprecated for unduly complicating both usage and implementation. You should instead use extractors for pattern matching on non-leaf nodes.
+ [warn] D:\temp\aste\Boogie\Chalice\src\main\scala\Ast.scala:111: case class `class TokenClass' has case class ancestor `class Class'. This has been deprecated for unduly complicating both usage and implementation. You should instead use extractors for pattern matching on non-leaf nodes.
+ [warn] D:\temp\aste\Boogie\Chalice\src\main\scala\Ast.scala:121: case class `class ChannelClass' has case class ancestor `class Class'. This has been deprecated for unduly complicating both usage and implementation. You should instead use extractors for pattern matching on non-leaf nodes.
+ [warn] D:\temp\aste\Boogie\Chalice\src\main\scala\Ast.scala:141: case class `class TokenType' has case class ancestor `class Type'. This has been deprecated for unduly complicating both usage and implementation. You should instead use extractors for pattern matching on non-leaf nodes.
+ [warn] D:\temp\aste\Boogie\Chalice\src\main\scala\Ast.scala:168: case class `class SpecialField' has case class ancestor `class Field'. This has been deprecated for unduly complicating both usage and implementation. You should instead use extractors for pattern matching on non-leaf nodes.
+ [warn] D:\temp\aste\Boogie\Chalice\src\main\scala\Ast.scala:227: case class `class SpecialVariable' has case class ancestor `class Variable'. This has been deprecated for unduly complicating both usage and implementation. You should instead use extractors for pattern matching on non-leaf nodes.
+# [2012-06-08 09:44:16] Released nightly of Chalice
|