blob: 92cd8b46b88d95ce540e29d553e648ada53933f3 [file] [log] [blame]
// 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.
library fasta.util.link;
import 'link_implementation.dart'
show LinkBuilderImplementation, LinkEntry, LinkIterator, MappedLinkIterable;
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, [String 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<K> map<K>(K fn(T item)) {
return new MappedLinkIterable<T, K>(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 ==(Object other) {
return other is Link<T> && other.isEmpty;
}
int get hashCode {
throw new UnsupportedError('Link.hashCode');
return 0;
}
String toString() => "[]";
int get length {
throw new UnsupportedError('get:length');
}
int slowLength() => 0;
// TODO(ahe): Remove this method?
bool contains(Object 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 e)) {
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)) { throw new UnsupportedError("any"); }
T elementAt(int i) { throw new UnsupportedError('elementAt'); }
Iterable<K> expand<K>(Iterable<K> f(T e)) { throw new UnsupportedError('expand'); }
T firstWhere(bool f(T e), {T orElse()}) { throw new UnsupportedError('firstWhere'); }
K fold<K>(K initialValue, K combine(K value, T element)) {
throw new UnsupportedError('fold');
}
T get last { throw new UnsupportedError('get:last'); }
T lastWhere(bool f(T e), {T orElse()}) { throw new UnsupportedError('lastWhere'); }
String join([String separator = '']) { throw new UnsupportedError('join'); }
T reduce(T combine(T a, T b)) { throw new UnsupportedError('reduce'); }
T singleWhere(bool f(T e)) { throw new UnsupportedError('singleWhere'); }
Iterable<T> skipWhile(bool f(T e)) { throw new UnsupportedError('skipWhile'); }
Iterable<T> take(int n) { throw new UnsupportedError('take'); }
Iterable<T> takeWhile(bool f(T e)) { throw new UnsupportedError('takeWhile'); }
Set<T> toSet() { throw new UnsupportedError('toSet'); }
Iterable<T> where(bool f(T e)) { throw new UnsupportedError('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<T>;
/// 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();
}