// -------------------------------------------------- module TestInductiveDatatypes { // The following types test for cycles that go via instantiated type arguments datatype Record = Ctor(T); datatype RecInt = Ctor(Record); // this is fine datatype Rec_Forever = Ctor(Record); // error datatype Rec_Stops = Cons(Record, Rec_Stops) | Nil; // this is okay datatype D = Ctor(E>); // error: illegal cycle datatype E = Ctor(T); // the following is okay datatype MD = Ctor(ME); datatype ME = Ctor(T); method M() { var d: MD>; } datatype A = Ctor(B); // superficially looks like a cycle, but can still be constructed datatype B = Ctor(List); datatype List = Nil | Cons(T, List); } module MoreInductive { datatype Tree = Node(G, List>); datatype List = Nil | Cons(T, List); datatype M = All(List); datatype H<'a> = HH('a, Tree<'a>); datatype K<'a> = KK('a, Tree>); // error datatype L<'a> = LL('a, Tree>>); } // -------------------------------------------------- module TestCoinductiveDatatypes { codatatype InfList = Done | Continue(T, InfList); codatatype Stream = More(T, Stream); codatatype BinaryTreeForever = BNode(val: T, left: BinaryTreeForever, right: BinaryTreeForever); datatype List = Nil | Cons(T, List); codatatype BestBushEver = Node(value: T, branches: List>); codatatype LazyRecord = Lazy(contents: T); class MyClass { } datatype GenericDt = Blue | Green(T); datatype GenericRecord = Rec(T); datatype FiniteEnough_Class = Ctor(MyClass); datatype FiniteEnough_Co = Ctor(LazyRecord); datatype FiniteEnough_Dt = Ctor(GenericDt); // fine datatype NotFiniteEnough_Dt = Ctor(GenericRecord); // error } // --------------- CoPredicates -------------------------- module CoPredicateResolutionErrors { codatatype Stream = StreamCons(head: T, tail: Stream); function Upward(n: int): Stream { StreamCons(n, Upward(n + 1)) } function Doubles(n: int): Stream { StreamCons(2*n, Doubles(n + 1)) } copredicate Pos(s: Stream) { 0 < s.head && Pos(s.tail) && Even(s) } copredicate Even(s: Stream) { s.head % 2 == 0 && Even(s.tail) && (s.head == 17 ==> Pos(s)) && (Pos(s) ==> s.head == 17) // error: cannot make recursive copredicate call in negative position && !Even(s) // error: cannot make recursive copredicate call in negative position && (Even(s) <==> Even(s)) // error (x2): recursive copredicate calls allowed only in positive positions } copredicate Another(s: Stream) { !Even(s) // here, negation is fine } ghost method Lemma(n: int) ensures Even(Doubles(n)); { } } // --------------------------------------------------