summaryrefslogtreecommitdiff
path: root/Test/dafny0/Reads.dfy
diff options
context:
space:
mode:
Diffstat (limited to 'Test/dafny0/Reads.dfy')
-rw-r--r--Test/dafny0/Reads.dfy81
1 files changed, 81 insertions, 0 deletions
diff --git a/Test/dafny0/Reads.dfy b/Test/dafny0/Reads.dfy
index 645494cb..6dedbada 100644
--- a/Test/dafny0/Reads.dfy
+++ b/Test/dafny0/Reads.dfy
@@ -55,3 +55,84 @@ function ok5(r : R):()
reads if r != null then {r, r.r} else {};
{()}
+// Reads checking where there are circularities among the expressions
+
+class CircularChecking {
+ ghost var Repr: set<object>
+
+ function F(): int
+ reads this, Repr
+
+ function F'(): int
+ reads Repr, this // this is also fine
+
+ function G0(): int
+ reads this
+ requires Repr == {} && F() == 100
+
+ function G1(): int
+ reads this
+ requires F() == 100 // fine, since the next line tells us that Repr is empty
+ requires Repr == {}
+
+ function H0(cell: Cell): int
+ reads Repr // by itself, this reads is not self-framing
+ requires this in Repr // lo and behold! So, reads clause is fine after all
+
+ function H1(cell: Cell): int
+ reads this, Repr
+ requires cell in Repr
+ requires cell != null && cell.data == 10
+
+ function H2(cell: Cell): int
+ reads this, Repr
+ requires cell != null && cell.data == 10 // this is okay, too, since reads checks are postponed
+ requires cell in Repr
+}
+
+class Cell { var data: int }
+
+// Test the benefits of the new reads checking for function checking
+
+function ApplyToSet<X>(S: set<X>, f: X -> X): set<X>
+ requires forall x :: x in S ==> f.reads(x) == {} && f.requires(x)
+{
+ if S == {} then {} else
+ var x :| x in S;
+ ApplyToSet(S - {x}, f) + {f(x)}
+}
+
+function ApplyToSet_AltSignature0<X>(S: set<X>, f: X -> X): set<X>
+ requires forall x :: x in S ==> f.requires(x) && f.reads(x) == {}
+
+function ApplyToSet_AltSignature1<X>(S: set<X>, f: X -> X): set<X>
+ requires forall x :: x in S ==> f.reads(x) == {}
+ requires forall x :: x in S ==> f.requires(x)
+
+function ApplyToSet_AltSignature2<X>(S: set<X>, f: X -> X): set<X>
+ requires (forall x :: x in S ==> f.reads(x) == {}) ==> forall x :: x in S ==> f.requires(x)
+ // (this precondition would not be good enough to check the body above)
+
+function FunctionInQuantifier0(): int
+ requires exists f: int -> int :: f(10) == 100 // error (x2): precondition violation and insufficient reads
+
+function FunctionInQuantifier1(): int
+ requires exists f: int -> int :: f.requires(10) && f(10) == 100 // error: insufficient reads
+
+function FunctionInQuantifier2(): int
+ requires exists f: int -> int :: f.reads(10) == {} && f.requires(10) && f(10) == 100
+ ensures FunctionInQuantifier2() == 100
+{
+ var f: int -> int :| f.reads(10) == {} && f.requires(10) && f(10) == 100; // fine :) :)
+ f(10)
+}
+
+class DynamicFramesIdiom {
+ ghost var Repr: set<object>
+ predicate IllFormed_Valid()
+ reads Repr // error: reads is not self framing (notice the absence of "this")
+ {
+ this in Repr // this says that the predicate returns true if "this in Repr", but the
+ // predicate can also be invoked in a state where its body will evaluate to false
+ }
+}