Index: tests/language/generic_methods_test.dart |
diff --git a/tests/language/generic_methods_test.dart b/tests/language/generic_methods_test.dart |
new file mode 100644 |
index 0000000000000000000000000000000000000000..fbad8244d0367c6fe383d614b0e60534592c1d52 |
--- /dev/null |
+++ b/tests/language/generic_methods_test.dart |
@@ -0,0 +1,110 @@ |
+// Copyright (c) 2016, 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. |
+// |
+// DartOptions=--generic-method-syntax |
+// AnalyzerOptions=--options=./generic_methods_test.options |
+ |
+import "package:expect/expect.dart"; |
+ |
+// Dart test verifying that the parser can handle type parameterization of |
+// method declarations and method invocations. Slightly adjusted version of |
+// code from DEP #22. |
+ |
+class BinaryTreeNode<K extends Comparable<K>, V> { |
+ final K _key; |
+ final V _value; |
+ final BinaryTreeNode<K, V> _left; |
+ final BinaryTreeNode<K, V> _right; |
+ |
+ BinaryTreeNode(this._key, this._value, |
+ {BinaryTreeNode<K, V> left: null, BinaryTreeNode<K, V> right: null}) : |
+ _left = left, _right = right; |
+ |
+ // Use fresh type variables. |
+ static BinaryTreeNode<K2, V2> insertOpt<K2 extends Comparable<K2>, V2>( |
+ BinaryTreeNode<K2, V2> t, K2 key, V2 value) { |
+ return (t == null) ? new BinaryTreeNode(key, value) : t.insert(key, value); |
+ } |
+ |
+ BinaryTreeNode<K, V> insert(K key, V value) { |
+ int c = key.compareTo(_key); |
+ if (c == 0) return this; |
+ var _insert = (BinaryTreeNode<K, V> node, K key, V value) => |
+ insertOpt<K, V>(node, key, value); |
+ BinaryTreeNode<K, V> left = _left; |
+ BinaryTreeNode<K, V> right = _right; |
+ if (c < 0) { |
+ left = _insert(_left, key, value); |
+ } else { |
+ right = _insert(_right, key, value); |
+ } |
+ return new BinaryTreeNode<K, V>(_key, _value, left: left, right: right); |
+ } |
+ |
+ // Reuse type variables [K], [V] to test shadowing. |
+ static BinaryTreeNode<K, U> mapOpt<K extends Comparable<K>, V, U> |
+ (BinaryTreeNode<K, V> t, U f(V x)) { |
+ return (t == null) ? null : t.map<U>(f); |
+ } |
+ |
+ BinaryTreeNode<K, U> map<U>(U f(V x)){ |
+ var _map = (BinaryTreeNode<K, V> t, U f(V x)) => mapOpt<K, V, U>(t, f); |
+ return new BinaryTreeNode<K, U>( |
+ _key, |
+ f(_value), |
+ left: _map(_left, f), |
+ right: _map(_right, f)); |
+ } |
+ |
+ // Use fresh [K2], shadowing [V]. |
+ static S foldPreOpt<K2 extends Comparable<K2>, V, S>( |
+ BinaryTreeNode<K2, V> t, S init, S f(V t, S s)) { |
+ return (t == null) ? init : t.foldPre<S>(init, f); |
+ } |
+ |
+ S foldPre<S>(S init, S f(V t, S s)) { |
+ var _fold = (BinaryTreeNode<K, V> t, S s, S f(V t, S s)) => |
+ foldPreOpt<K, V, S>(t, s, f); |
+ S s = init; |
+ s = f(_value, s); |
+ s = _fold(_left, s, f); |
+ s = _fold(_right, s, f); |
+ return s; |
+ } |
+} |
+ |
+class BinaryTree<K extends Comparable<K>, V> { |
+ final BinaryTreeNode<K, V> _root; |
+ |
+ BinaryTree._internal(this._root); |
+ BinaryTree.empty() : this._internal(null); |
+ |
+ BinaryTree<K, V> insert(K key, V value) { |
+ BinaryTreeNode<K, V> root = |
+ BinaryTreeNode.insertOpt<K, V>(_root, key, value); |
+ return new BinaryTree<K, V>._internal(root); |
+ } |
+ |
+ BinaryTree<K, U> map<U>(U f(V x)) { |
+ BinaryTreeNode<K, U> root = BinaryTreeNode.mapOpt<K, V, U>(_root, f); |
+ return new BinaryTree<K, U>._internal(root); |
+ } |
+ |
+ S foldPre<S>(S init, S f(V t, S s)) { |
+ return BinaryTreeNode.foldPreOpt<K, V, S>(_root, init, f); |
+ } |
+} |
+ |
+main() { |
+ BinaryTree<num, String> sT = new BinaryTree<num, String>.empty(); |
+ |
+ sT = sT.insert(0, ""); |
+ sT = sT.insert(1, " "); |
+ sT = sT.insert(2, " "); |
+ sT = sT.insert(3, " "); |
+ |
+ BinaryTree<num, num> iT = sT.map<num>((String s) => s.length); |
+ |
+ Expect.equals(iT.foldPre<num>(0, (int i, num s) => i + s), 6); |
+} |