Index: pkg/compiler_util/lib/link.dart |
diff --git a/pkg/compiler_util/lib/link.dart b/pkg/compiler_util/lib/link.dart |
new file mode 100644 |
index 0000000000000000000000000000000000000000..58d2cb98cf09b71e3abc52de0d149b02ebbaa9cb |
--- /dev/null |
+++ b/pkg/compiler_util/lib/link.dart |
@@ -0,0 +1,172 @@ |
+// Copyright (c) 2011, 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. |
+ |
+part of dart2js.util; |
+ |
+class Link<T> implements Iterable<T> { |
+ T get head => throw new StateError("no elements"); |
+ Link<T> get tail => null; |
+ |
+ const Link(); |
+ |
+ Link<T> prepend(T element) { |
+ return new LinkEntry<T>(element, this); |
+ } |
+ |
+ Iterator<T> get iterator => new LinkIterator<T>(this); |
+ |
+ void printOn(StringBuffer buffer, [separatedBy]) {} |
+ |
+ List<T> toList({bool growable: true}) { |
+ List<T> result; |
+ if (!growable) { |
+ result = new List<T>(slowLength()); |
+ } else { |
+ result = new List<T>(); |
+ result.length = slowLength(); |
+ } |
+ int i = 0; |
+ for (Link<T> link = this; !link.isEmpty; link = link.tail) { |
+ result[i++] = link.head; |
+ } |
+ return result; |
+ } |
+ |
+ /// Lazily maps over this linked list, returning an [Iterable]. |
+ Iterable map(dynamic fn(T item)) { |
+ return new MappedLinkIterable<T, dynamic>(this, fn); |
+ } |
+ |
+ /// Invokes `fn` for every item in the linked list and returns the results |
+ /// in a [List]. |
+ List mapToList(dynamic fn(T item), {bool growable: true}) { |
+ List result; |
+ if (!growable) { |
+ result = new List(slowLength()); |
+ } else { |
+ result = new List(); |
+ result.length = slowLength(); |
+ } |
+ int i = 0; |
+ for (Link<T> link = this; !link.isEmpty; link = link.tail) { |
+ result[i++] = fn(link.head); |
+ } |
+ return result; |
+ } |
+ |
+ bool get isEmpty => true; |
+ bool get isNotEmpty => false; |
+ |
+ Link<T> reverse() => this; |
+ |
+ Link<T> reversePrependAll(Link<T> from) { |
+ if (from.isEmpty) return this; |
+ return this.prepend(from.head).reversePrependAll(from.tail); |
+ } |
+ |
+ Link<T> skip(int n) { |
+ if (n == 0) return this; |
+ throw new RangeError('Index $n out of range'); |
+ } |
+ |
+ void forEach(void f(T element)) {} |
+ |
+ bool operator ==(other) { |
+ if (other is! Link<T>) return false; |
+ return other.isEmpty; |
+ } |
+ |
+ int get hashCode => throw new UnsupportedError('Link.hashCode'); |
+ |
+ String toString() => "[]"; |
+ |
+ get length { |
+ throw new UnsupportedError('get:length'); |
+ } |
+ |
+ int slowLength() => 0; |
+ |
+ // TODO(ahe): Remove this method? |
+ bool contains(T element) { |
+ for (Link<T> link = this; !link.isEmpty; link = link.tail) { |
+ if (link.head == element) return true; |
+ } |
+ return false; |
+ } |
+ |
+ // TODO(ahe): Remove this method? |
+ T get single { |
+ if (isEmpty) throw new StateError('No elements'); |
+ if (!tail.isEmpty) throw new StateError('More than one element'); |
+ return head; |
+ } |
+ |
+ // TODO(ahe): Remove this method? |
+ T get first { |
+ if (isEmpty) throw new StateError('No elements'); |
+ return head; |
+ } |
+ |
+ /// Returns true if f returns true for all elements of this list. |
+ /// |
+ /// Returns true for the empty list. |
+ bool every(bool f(T)) { |
+ for (Link<T> link = this; !link.isEmpty; link = link.tail) { |
+ if (!f(link.head)) return false; |
+ } |
+ return true; |
+ } |
+ |
+ Link copyWithout(e) => this; |
+ |
+ // |
+ // Unsupported Iterable<T> methods. |
+ // |
+ bool any(bool f(T e)) => _unsupported('any'); |
+ T elementAt(int i) => _unsupported('elementAt'); |
+ Iterable expand(Iterable f(T e)) => _unsupported('expand'); |
+ T firstWhere(bool f(T e), {T orElse()}) => _unsupported('firstWhere'); |
+ fold(initialValue, combine(value, T element)) => _unsupported('fold'); |
+ T get last => _unsupported('get:last'); |
+ T lastWhere(bool f(T e), {T orElse()}) => _unsupported('lastWhere'); |
+ String join([separator = '']) => _unsupported('join'); |
+ T reduce(T combine(T a, T b)) => _unsupported('reduce'); |
+ T singleWhere(bool f(T e)) => _unsupported('singleWhere'); |
+ Iterable<T> skipWhile(bool f(T e)) => _unsupported('skipWhile'); |
+ Iterable<T> take(int n) => _unsupported('take'); |
+ Iterable<T> takeWhile(bool f(T e)) => _unsupported('takeWhile'); |
+ Set<T> toSet() => _unsupported('toSet'); |
+ Iterable<T> where(bool f(T e)) => _unsupported('where'); |
+ |
+ _unsupported(String method) => throw new UnsupportedError(method); |
+} |
+ |
+/// Builder object for creating linked lists using [Link] or fixed-length [List] |
+/// objects. |
+abstract class LinkBuilder<T> { |
+ factory LinkBuilder() = LinkBuilderImplementation; |
+ |
+ /// Prepends all elements added to the builder to [tail]. The resulting list |
+ /// is returned and the builder is cleared. |
+ Link<T> toLink([Link<T> tail = const Link()]); |
+ |
+ /// Creates a new fixed length containing all added elements. The |
+ /// resulting list is returned and the builder is cleared. |
+ List<T> toList(); |
+ |
+ /// Adds the element [t] to the end of the list being built. |
+ Link<T> addLast(T t); |
+ |
+ /// Returns the first element in the list being built. |
+ T get first; |
+ |
+ /// Returns the number of elements in the list being built. |
+ final int length; |
+ |
+ /// Returns `true` if the list being built is empty. |
+ final bool isEmpty; |
+ |
+ /// Removes all added elements and resets the builder. |
+ void clear(); |
+} |