|  | // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file | 
|  | // for details. All rights reserved. Use of this source code is governed by a | 
|  | // BSD-style license that can be found in the LICENSE file. | 
|  |  | 
|  | import "package:expect/expect.dart"; | 
|  |  | 
|  | // Dart test for deeply nested generic types. | 
|  |  | 
|  | /** A natural number aka Peano number. */ | 
|  | abstract class N { | 
|  | N add1(); | 
|  | N sub1(); | 
|  | } | 
|  |  | 
|  | /** Zero element. */ | 
|  | class Z implements N { | 
|  | Z(); | 
|  | N add1() { return new S<Z>(this); } | 
|  | N sub1() { throw "Error: sub1(0)"; } | 
|  | } | 
|  |  | 
|  | /** Successor element. */ | 
|  | class S<K> implements N { | 
|  | N before; | 
|  | S(this.before); | 
|  | N add1() { return new S<S<K>>(this); } | 
|  | N sub1() { | 
|  | // It would be super cool if this could be "new K()". | 
|  | return before; | 
|  | } | 
|  | } | 
|  |  | 
|  | N NFromInt(int x) { | 
|  | if (x == 0) | 
|  | return new Z(); | 
|  | else | 
|  | return NFromInt(x - 1).add1(); | 
|  | } | 
|  |  | 
|  | int IntFromN(N x) { | 
|  | if (x is Z) | 
|  | return 0; | 
|  | if (x is S) | 
|  | return IntFromN(x.sub1()) + 1; | 
|  | throw "Error"; | 
|  | } | 
|  |  | 
|  | bool IsEven(N x) { | 
|  | if (x is Z) return true; | 
|  | if (x is S<Z>) return false; | 
|  | if (x is S<S>) return IsEven(x.sub1().sub1()); | 
|  | throw "Error in IsEven"; | 
|  | } | 
|  |  | 
|  | main() { | 
|  | Expect.isTrue(NFromInt(0) is Z); | 
|  | Expect.isTrue(NFromInt(1) is S<Z>); | 
|  | Expect.isTrue(NFromInt(2) is S<S<Z>>); | 
|  | Expect.isTrue(NFromInt(3) is S<S<S<Z>>>); | 
|  | Expect.isTrue(NFromInt(10) is S<S<S<S<S<S<S<S<S<S<Z>>>>>>>>>>); | 
|  |  | 
|  | // Negative tests. | 
|  | Expect.isTrue(NFromInt(0) is !S); | 
|  | Expect.isTrue(NFromInt(1) is !Z); | 
|  | Expect.isTrue(NFromInt(1) is !S<S>); | 
|  | Expect.isTrue(NFromInt(2) is !Z); | 
|  | Expect.isTrue(NFromInt(2) is !S<Z>); | 
|  | Expect.isTrue(NFromInt(2) is !S<S<S>>); | 
|  |  | 
|  | // Greater-than tests | 
|  | Expect.isTrue(NFromInt(4) is S<S>);            // 4 >= 2 | 
|  | Expect.isTrue(NFromInt(4) is S<S<S>>);         // 4 >= 3 | 
|  | Expect.isTrue(NFromInt(4) is S<S<S<S>>>);      // 4 >= 4 | 
|  | Expect.isTrue(NFromInt(4) is !S<S<S<S<S>>>>);  // 4 < 5 | 
|  |  | 
|  | Expect.isTrue(IsEven(NFromInt(0))); | 
|  | Expect.isFalse(IsEven(NFromInt(1))); | 
|  | Expect.isTrue(IsEven(NFromInt(2))); | 
|  | Expect.isFalse(IsEven(NFromInt(3))); | 
|  | Expect.isTrue(IsEven(NFromInt(4))); | 
|  |  | 
|  | Expect.equals(0, IntFromN(NFromInt(0))); | 
|  | Expect.equals(1, IntFromN(NFromInt(1))); | 
|  | Expect.equals(2, IntFromN(NFromInt(2))); | 
|  | Expect.equals(50, IntFromN(NFromInt(50))); | 
|  | } |