diff options
author | Martin Odersky <odersky@gmail.com> | 2009-02-05 19:25:43 +0000 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2009-02-05 19:25:43 +0000 |
commit | 0ecacced0347e4e3b83989a274b9de53868a3a57 (patch) | |
tree | cf5bb351b3acef82ad88862bee320b9c6e32a4c3 /src/library/scalax | |
parent | 48355ee28a930f19000901d761f24ca44b324c1f (diff) | |
download | scala-0ecacced0347e4e3b83989a274b9de53868a3a57.tar.gz scala-0ecacced0347e4e3b83989a274b9de53868a3a57.tar.bz2 scala-0ecacced0347e4e3b83989a274b9de53868a3a57.zip |
added support for Strings, arrays, sets.
Diffstat (limited to 'src/library/scalax')
49 files changed, 1832 insertions, 133 deletions
diff --git a/src/library/scalax/collection/Builder.scala b/src/library/scalax/collection/Builder.scala index 87219c803b..2c80916d50 100755 --- a/src/library/scalax/collection/Builder.scala +++ b/src/library/scalax/collection/Builder.scala @@ -10,12 +10,22 @@ package scalax.collection - -trait Builder[+CC[B], A] extends mutable.Appendable[A] { +trait Builder[+CC[B], A] extends generic.mutable.Growable[A] { def +=(x: A) def elements: Iterator[A] def result: CC[A] override def ++=(xs: Iterator[A]) { for (x <- xs) this += x } override def ++=(xs: Iterable[A]) { for (x <- xs) this += x } + + def mapResult[DD[B]](f: CC[A] => DD[A]) = + new Builder[DD, A] with Proxy { + val self = Builder.this + def +=(x: A) = self += x + def elements: Iterator[A] = self.elements + def clear() = self.clear() + override def ++=(xs: Iterator[A]) = self ++= xs + override def ++=(xs: collection.Iterable[A]) = self ++= xs + def result: DD[A] = f(Builder.this.result) + } } diff --git a/src/library/scalax/collection/Iterable.scala b/src/library/scalax/collection/Iterable.scala index fa0dd34ecc..08bf338290 100755 --- a/src/library/scalax/collection/Iterable.scala +++ b/src/library/scalax/collection/Iterable.scala @@ -122,11 +122,11 @@ object Iterable extends covariant.IterableFactory[Iterable] { implicit def pairIterableWrapper[C[+B] <: Iterable[B], A1, A2](seq: C[(A1, A2)]) = new PairIterableOps[C, A1, A2](seq) - type View[+UC[+B] <: Sequence[B], +A] = covariant.IterableView[UC, A] + type View[+UC[B] <: Sequence[B], A] = IterableView[UC, A] /** @deprecated use View instead */ - @deprecated type Projection[+A] = View[C, A] forSome { type C[B] <: Iterable[B] } + @deprecated type Projection[A] = View[C, A] forSome { type C[B] <: Iterable[B] } /** The minimum element of a non-empty sequence of ordered elements * @deprecated use seq.min instead diff --git a/src/library/scalax/collection/Sequence.scala b/src/library/scalax/collection/Sequence.scala index 31f486406f..90212b3b5e 100755 --- a/src/library/scalax/collection/Sequence.scala +++ b/src/library/scalax/collection/Sequence.scala @@ -21,14 +21,14 @@ import immutable.Nil * @author Matthias Zenger * @version 1.0, 16/07/2003 */ -trait Sequence[+A] extends OrderedIterable[A] with SizedIterable[A] with covariant.SequenceTemplate[Sequence, A] +trait Sequence[+A] extends OrderedIterable[A] with SizedIterable[A] with generic.covariant.SequenceTemplate[Sequence, A] object Sequence extends covariant.SequenceFactory[Sequence] { /** The empty sequence */ val empty : Sequence[Nothing] = immutable.Nil - type View[+UC[+B] <: Sequence[B], +A] = covariant.SequenceView[UC, A] + type View[+UC[B] <: Sequence[B], A] = SequenceView[UC, A] /** @deprecated use View instead */ diff --git a/src/library/scalax/collection/generic/covariant/IterableView.scala b/src/library/scalax/collection/Set.scala index 728b065d55..24829364b3 100755..100644 --- a/src/library/scalax/collection/generic/covariant/IterableView.scala +++ b/src/library/scalax/collection/Set.scala @@ -8,14 +8,16 @@ // $Id: Iterable.scala 15188 2008-05-24 15:01:02Z stepancheg $ -package scalax.collection.generic.covariant +package scalax.collection + +import generic._ + +trait Set[A] extends OrderedIterable[A] with SetTemplate[Set, A] + +/* Factory object for `Sequence` class */ +object Set extends IterableFactory[Set] { + /** The empty set */ + def apply[A](args: A*): Set[A] = null // !!! +} -import annotation.unchecked.uncheckedVariance -/** A non-strict projection of an iterable. - * @author Sean McDirmid - * @author Martin Odersky - * @note this should really be a virtual class of SequenceFactory - */ -trait IterableView[+UC[+B] <: Iterable[B], +A] - extends generic.IterableView[UC, A @uncheckedVariance] diff --git a/src/library/scalax/collection/generic/covariant/SequenceView.scala b/src/library/scalax/collection/generic/Cloneable.scala index eba1795d13..455c88e47b 100755..100644 --- a/src/library/scalax/collection/generic/covariant/SequenceView.scala +++ b/src/library/scalax/collection/generic/Cloneable.scala @@ -6,17 +6,13 @@ ** |/ ** \* */ -// $Id: Sequence.scala 16092 2008-09-12 10:37:06Z nielsen $ +// $Id: CloneableCollection.scala 16893 2009-01-13 13:09:22Z cunei $ -package scalax.collection.generic.covariant +package scala.collection.generic -import annotation.unchecked.uncheckedVariance - -/** A non-strict projection of an iterable. - * @author Sean McDirmid - * @author Martin Odersky - * @note this should really be a virtual class of SequenceFactory +/** A trait for cloneable collections. */ -trait SequenceView[+UC[+B] <: Sequence[B], +A] - extends IterableView[UC, A] with generic.SequenceView[UC, A @uncheckedVariance] +trait Cloneable[A <: AnyRef] extends java.lang.Cloneable { + override def clone(): A = super.clone().asInstanceOf[A] +} diff --git a/src/library/scalax/collection/generic/IterableFactory.scala b/src/library/scalax/collection/generic/IterableFactory.scala index 1362e97079..9570970abe 100755 --- a/src/library/scalax/collection/generic/IterableFactory.scala +++ b/src/library/scalax/collection/generic/IterableFactory.scala @@ -26,7 +26,7 @@ trait IterableFactory[CC[A] <: Iterable[A]] { * @param n The number of elements returned * @param elem The element returned each time */ - def fill[A](n: Int, elem: => A): CC[A] = { + def fill[A](n: Int)(elem: => A): CC[A] = { val b = newBuilder[A] var i = 0 while (i < n) { @@ -36,11 +36,17 @@ trait IterableFactory[CC[A] <: Iterable[A]] { b.result } - def fill[A](n1: Int, n2: Int, elem: => A): CC[CC[A]] = - tabulate(n1)(_ => fill(n2, elem)) + def fill[A](n1: Int, n2: Int)(elem: => A): CC[CC[A]] = + tabulate(n1)(_ => fill(n2)(elem)) - def fill[A](n1: Int, n2: Int, n3: Int, elem: => A): CC[CC[CC[A]]] = - tabulate(n1)(_ => fill(n2, n3, elem)) + def fill[A](n1: Int, n2: Int, n3: Int)(elem: => A): CC[CC[CC[A]]] = + tabulate(n1)(_ => fill(n2, n3)(elem)) + + def fill[A](n1: Int, n2: Int, n3: Int, n4: Int)(elem: => A): CC[CC[CC[CC[A]]]] = + tabulate(n1)(_ => fill(n2, n3, n4)(elem)) + + def fill[A](n1: Int, n2: Int, n3: Int, n4: Int, n5: Int)(elem: => A): CC[CC[CC[CC[CC[A]]]]] = + tabulate(n1)(_ => fill(n2, n3, n4, n5)(elem)) def tabulate[A](n: Int)(f: Int => A): CC[A] = { val b = newBuilder[A] @@ -53,11 +59,16 @@ trait IterableFactory[CC[A] <: Iterable[A]] { } def tabulate[A](n1: Int, n2: Int)(f: (Int, Int) => A): CC[CC[A]] = - tabulate(n1)(i1 => tabulate(n2)(i2 => f(i1, i2))) + tabulate(n1)(i1 => tabulate(n2)(f(i1, _))) def tabulate[A](n1: Int, n2: Int, n3: Int)(f: (Int, Int, Int) => A): CC[CC[CC[A]]] = - tabulate(n1)(i1 => tabulate(n2)(i2 => tabulate(n3)(i3 => f(i1, i2, i3)))) -// todo: go up to 5(?) + tabulate(n1)(i1 => tabulate(n2, n3)(f(i1, _, _))) + + def tabulate[A](n1: Int, n2: Int, n3: Int, n4: Int)(f: (Int, Int, Int, Int) => A): CC[CC[CC[CC[A]]]] = + tabulate(n1)(i1 => tabulate(n2, n3, n4)(f(i1, _, _, _))) + + def tabulate[A](n1: Int, n2: Int, n3: Int, n4: Int, n5: Int)(f: (Int, Int, Int, Int, Int) => A): CC[CC[CC[CC[CC[A]]]]] = + tabulate(n1)(i1 => tabulate(n2, n3, n4, n5)(f(i1, _, _, _, _))) /** Create a sequence of increasing integers in a range. * diff --git a/src/library/scalax/collection/generic/IterableTemplate.scala b/src/library/scalax/collection/generic/IterableTemplate.scala index c2f1fadd9c..adbf5d2de7 100755 --- a/src/library/scalax/collection/generic/IterableTemplate.scala +++ b/src/library/scalax/collection/generic/IterableTemplate.scala @@ -56,6 +56,11 @@ trait IterableTemplate[+CC[/*+*/B] <: IterableTemplate[CC, B] with Iterable[B], */ def newBuilder[B]: Builder[CC, B] + /** Create a new builder for this IterableType + * with a hint what that its size should be size `sizeHint` + */ + def newBuilder[B](sizeHint: Int): Builder[CC, B] = newBuilder[B] + /** Is this collection empty? */ def isEmpty: Boolean = !elements.hasNext @@ -542,7 +547,6 @@ b * @param thatElem element <code>thatElem</code> is used to fill up the string } - /** Creates a view of this iterable @see IterableView */ def view: IterableView[CC, A] = new IterableView[CC, A] { // !!! Martin: We should maybe infer the type parameters here? diff --git a/src/library/scalax/collection/generic/SequenceTemplate.scala b/src/library/scalax/collection/generic/SequenceTemplate.scala index 27bba86ba0..3407f63216 100755 --- a/src/library/scalax/collection/generic/SequenceTemplate.scala +++ b/src/library/scalax/collection/generic/SequenceTemplate.scala @@ -324,6 +324,9 @@ self /*: CC[A]*/ => */ override def toSequence: Sequence[A] = thisCC + /** Force toString from Iterable, not from Function */ + override def toString = super[OrderedIterableTemplate].toString + def indices: Range = 0 until length /** Creates a view of this iterable @see OrderedIterable.View diff --git a/src/library/scalax/collection/generic/SequenceView.scala b/src/library/scalax/collection/generic/SequenceView.scala index 72e863d4f2..aa6f1e50f8 100755 --- a/src/library/scalax/collection/generic/SequenceView.scala +++ b/src/library/scalax/collection/generic/SequenceView.scala @@ -97,7 +97,7 @@ self => if (0 <= from && from < length) new Patched(from, patch, replaced).asCC else throw new IndexOutOfBoundsException(from.toString) override def padTo[B >: A](len: Int, elem: B): SequenceView[UC, B] = - patch(length, fill((len - length) max 0, elem), 0) + patch(length, fill((len - length) max 0)(elem), 0) override def zip[B](that: Iterable[B]): SequenceView[UC, (A, B)] = new Zipped(that.toSequence).asCC override def zipWithIndex: SequenceView[UC, (A, Int)] = diff --git a/src/library/scalax/collection/generic/SetFactory.scala b/src/library/scalax/collection/generic/SetFactory.scala new file mode 100644 index 0000000000..0fbcf68466 --- /dev/null +++ b/src/library/scalax/collection/generic/SetFactory.scala @@ -0,0 +1,9 @@ +package scalax.collection.generic + +trait SetFactory[CC[A] <: SetTemplate[CC, A] with Set[A]] extends IterableFactory[CC] { + + def empty[A]: CC[A] + + def apply[A](elems: A*): CC[A] = empty[A] ++ elems.asInstanceOf[Iterable[A]] // !@! + +} diff --git a/src/library/scalax/collection/generic/SetTemplate.scala b/src/library/scalax/collection/generic/SetTemplate.scala new file mode 100755 index 0000000000..9c3056cc04 --- /dev/null +++ b/src/library/scalax/collection/generic/SetTemplate.scala @@ -0,0 +1,173 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id: Set.scala 16893 2009-01-13 13:09:22Z cunei $ + + +package scalax.collection.generic + + +/** <p> + * A set is a collection that includes at most one of any object. + * </p> + * <p> + * This trait provides a limited interface, only allowing reading of elements. + * There are two extensions of this trait, in packages + * <code><a href="mutable$content.html" target="contentFrame"> + * scala.collection.mutable</a></code> + * and <code><a href="immutable$content.html" target="contentFrame"> + * scala.collection.immutable</a></code>, which provide functionality for + * adding and removing objects from the set. The trait in the first package is + * for sets that are modified destructively, whereas the trait in + * the second package is for immutable sets which create a new set + * when something is added or removed to them. + * + * @author Matthias Zenger + * @author Martin Odersky + * @version 2.8 + */ +trait SetTemplate[+CC[B] <: SetTemplate[CC, B] with Set[B], A] extends (A => Boolean) with SizedIterable[A] with OrderedIterableTemplate[CC, A] { + + /** Returns the number of elements in this set. + * + * @return number of set elements. + */ + def size: Int + + /** Creates a new set of this kind with given elements */ + def newBuilder[B]: Builder[CC, B] + + /** Checks if this set contains element <code>elem</code>. + * + * @param elem the element to check for membership. + * @return <code>true</code> iff <code>elem</code> is contained in + * this set. + */ + def contains(elem: A): Boolean + + /** Create a new set with an additional element. + */ + def +(elem: A): CC[A] + + /** Remove a single element from a set. + * @param elem the element to be removed + * @return a new set with the element removed. + */ + def -(elem: A): CC[A] + + /** Checks if this set is empty. + * + * @return <code>true</code> iff there is no element in the set. + */ + override def isEmpty: Boolean = size == 0 + + /** This method allows sets to be interpreted as predicates. + * It returns <code>true</code>, iff this set contains element + * <code>elem</code>. + * + * @param elem the element to check for membership. + * @return <code>true</code> iff <code>elem</code> is contained in + * this set. + */ + def apply(elem: A): Boolean = contains(elem) + + /** Add two or more elements to this set. + * @param elem1 the first element. + * @param elem2 the second element. + * @param elems the remaining elements. + * @return a new set with the elements added. + */ + def + (elem1: A, elem2: A, elems: A*): CC[A] = { + thisCC + elem1 + elem2 ++ elems.asInstanceOf[Iterable[A]] + } + + /** Remove two or more elements from this set. + * + * @param elem1 the first element. + * @param elem2 the second element. + * @param elems the remaining elements. + * @return a new set with the elements removed. + */ + def - (elem1: A, elem2: A, elems: A*): CC[A] = + this - elem1 - elem2 -- elems.asInstanceOf[Iterable[A]] + + /** Remove all the elements provided by an iterator + * of the iterable object <code>elems</code> from the set. + * + * @param elems An iterable object containing the elements to remove from the set. + * @return a new set with the elements removed. + */ + def -- (elems: Iterable[A]): CC[A] = this -- elems.elements + + /** Remove all the elements provided by an iterator + * <code>elems</code> from the set. + * + * @param elems An iterator containing the elements to remove from the set. + * @return a new set with the elements removed. + */ + def -- (elems: Iterator[A]): CC[A] = + (thisCC /: elems) (_ - _) + + /** This method computes an intersection with set <code>that</code>. + * It removes all the elements that are not present in <code>that</code>. + * + * @param that the set to intersect with. + */ + def intersect(that: Set[A]): CC[A] = filter(that.contains) + + /** This method is an alias for <code>intersect</code>. + * It computes an intersection with set <code>that</code>. + * It removes all the elements that are not present in <code>that</code>. + * + * @param that the set to intersect with + */ + def ** (that: collection.Set[A]): CC[A] = intersect(that) + + /** Checks if this set is a subset of set <code>that</code>. + * + * @param that another set. + * @return <code>true</code> iff the other set is a superset of + * this set. + * todo: rename to isSubsetOf + */ + def subsetOf(that: Set[A]): Boolean = forall(that.contains) + + /** Compares this set with another object and returns true, iff the + * other object is also a set which contains the same elements as + * this set. + * + * @param that the other object + * @note not necessarily run-time type safe. + * @return <code>true</code> iff this set and the other set + * contain the same elements. + * @deprecated equals is not stable for mutable sets. + * If you wish object identity, use eq or cast this set of AnyRef and then use + * equals. If you wish element comparisons, use `sameElements` instead. + */ + @deprecated override def equals(that: Any): Boolean = that match { + case other: Set[_] => + this.size == other.size && subsetOf(other.asInstanceOf[Set[A]]) + case _ => + false + } + + /* @deprecated hashCode is not stable for mutable sets. + * if you intend to have object identity hashCode and wish the deprecated warning + * to go away, cast this set to AnyRef before calling hashCode. + */ + @deprecated override def hashCode() = + (0 /: this)((hash, e) => hash + e.hashCode()) + + /** Defines the prefix of this object's <code>toString</code> representation. + */ + override def stringPrefix: String = "Set" + + /** Need to override string, so that it's not the Function1's string that gets mixed in. + */ + override def toString = super[OrderedIterableTemplate].toString +} diff --git a/src/library/scalax/collection/generic/VectorTemplate.scala b/src/library/scalax/collection/generic/VectorTemplate.scala index 854f4fb3a2..d97fd03aa4 100644 --- a/src/library/scalax/collection/generic/VectorTemplate.scala +++ b/src/library/scalax/collection/generic/VectorTemplate.scala @@ -89,7 +89,7 @@ self => case that: Vector[_] => var i = 0 val len = this.length min that.length - val b = this.newBuilder[(A, B)] + val b = this.newBuilder[(A, B)](len) while (i < len) { b += ((this(i), that(i).asInstanceOf[B])) i += 1 @@ -102,8 +102,10 @@ self => override def zipAll[B, A1 >: A, B1 >: B](that: Iterable[B], thisElem: A1, thatElem: B1): CC[(A1, B1)] = that match { case that: Vector[_] => var i = 0 - val len = this.length min that.length - val b = this.newBuilder[(A1, B1)] + val thisLen = this.length + val thatLen = that.length + val len = thisLen min thatLen + val b = this.newBuilder[(A1, B1)](thisLen max thatLen) while (i < len) { b += ((this(i), that(i).asInstanceOf[B])) i += 1 @@ -122,9 +124,9 @@ self => } override def zipWithIndex: CC[(A, Int)] = { - val b = newBuilder[(A, Int)] - var i = 0 val len = length + val b = newBuilder[(A, Int)](len) + var i = 0 while (i < len) { b += ((this(i), i)) i += 1 @@ -148,9 +150,9 @@ self => override def head: A = if (isEmpty) throw new NoSuchElementException else this(0) override def slice(from: Int, until: Int): CC[A] = { - val b = newBuilder[A] var i = from max 0 val end = until min length + val b = newBuilder[A](end - i) while (i < end) { b += this(i) i += 1 @@ -199,7 +201,7 @@ self => override def lastIndexOf[B >: A](elem: B, end: Int): Int = lastIndexWhere(elem ==, end) override def reverse: CC[A] = { - val b = newBuilder[A] + val b = newBuilder[A](length) var i = length while (0 < i) { i -= 1 diff --git a/src/library/scalax/collection/generic/covariant/IterableTemplate.scala b/src/library/scalax/collection/generic/covariant/IterableTemplate.scala index ae9cd5e1d9..715f88cd8e 100755 --- a/src/library/scalax/collection/generic/covariant/IterableTemplate.scala +++ b/src/library/scalax/collection/generic/covariant/IterableTemplate.scala @@ -23,7 +23,17 @@ import annotation.unchecked.uncheckedVariance * @version 1.1, 04/02/2004 */ trait IterableTemplate[+CC[+B] <: IterableTemplate[CC, B] with Iterable[B], +A] - extends generic.IterableTemplate[CC, A @uncheckedVariance] { self /*: CC[A]*/ => } + extends generic.IterableTemplate[CC, A @uncheckedVariance] { self /*: CC[A]*/ => + +/* can't have a covariant view here, because mutable.Vector would + override it + override def view: IterableView[CC, A] = new IterableView[CC, A] { + val origin = thisCC + val elements: Iterator[A] = self.elements + } +*/ +} + // !!! todo: explain why @uncheckedVariance is justified here. diff --git a/src/library/scalax/collection/generic/covariant/SequenceTemplate.scala b/src/library/scalax/collection/generic/covariant/SequenceTemplate.scala index 2e30e05fbf..1e8a416aec 100755 --- a/src/library/scalax/collection/generic/covariant/SequenceTemplate.scala +++ b/src/library/scalax/collection/generic/covariant/SequenceTemplate.scala @@ -14,4 +14,4 @@ package scalax.collection.generic.covariant import annotation.unchecked.uncheckedVariance trait SequenceTemplate[+CC[+B] <: SequenceTemplate[CC, B] with Sequence[B], +A] - extends generic.SequenceTemplate[CC, A @uncheckedVariance] {self /*: CC[A]*/ => } + extends generic.SequenceTemplate[CC, A @uncheckedVariance] diff --git a/src/library/scalax/collection/generic/covartest/SequenceView.scala b/src/library/scalax/collection/generic/covartest/SequenceView.scala index bae43636ae..77b06b0b4f 100755 --- a/src/library/scalax/collection/generic/covartest/SequenceView.scala +++ b/src/library/scalax/collection/generic/covartest/SequenceView.scala @@ -97,7 +97,7 @@ self => if (0 <= from && from < length) new Patched(from, patch, replaced).asCC else throw new IndexOutOfBoundsException(from.toString) override def padTo[B >: A](len: Int, elem: B): SequenceView[UC, B] = - patch(length, fill((len - length) max 0, elem), 0) + patch(length, fill((len - length) max 0)(elem), 0) override def zip[B](that: Iterable[B]): SequenceView[UC, (A, B)] = new Zipped(that.toSequence).asCC override def zipWithIndex: SequenceView[UC, (A, Int)] = diff --git a/src/library/scalax/collection/mutable/Appendable.scala b/src/library/scalax/collection/generic/mutable/Growable.scala index 8a45724bff..4d585129ad 100644 --- a/src/library/scalax/collection/mutable/Appendable.scala +++ b/src/library/scalax/collection/generic/mutable/Growable.scala @@ -8,7 +8,7 @@ // $Id: Iterable.scala 15188 2008-05-24 15:01:02Z stepancheg $ -package scalax.collection.mutable +package scalax.collection.generic.mutable /** This class represents collections that can be augmented using a += operator. * @@ -16,19 +16,19 @@ package scalax.collection.mutable * @owner Martin Odersky * @version 2.8 */ -trait Appendable[A] { +trait Growable[A] { - /** Append a single element to this buffer. + /** Add a single element to this collection. * - * @param elem the element to append. + * @param elem the element to add. */ def +=(elem: A): Unit - /** Append a two or more elements to this buffer. + /** Add a two or more elements to this collection. * - * @param elem1 the first element to append. - * @param elem2 the second element to append. - * @param elems the remaining elements to append. + * @param elem1 the first element to add. + * @param elem2 the second element to add. + * @param elems the remaining elements to add. */ def +=(elem1: A, elem2: A, elems: A*) { this += elem1 @@ -36,55 +36,55 @@ trait Appendable[A] { this ++= elems.asInstanceOf[Iterable[A]] // !@! } - /** Appends a number of elements provided by an iterator + /** Adds a number of elements provided by an iterator * * @param iter the iterator. */ def ++=(iter: collection.Iterator[A]) { iter foreach += } - /** Appends a number of elements provided by an iterable object + /** Adds a number of elements provided by an iterable object * via its <code>elements</code> method. * * @param iter the iterable object. */ def ++=(iter: collection.Iterable[A]) { iter foreach += } - /** Append a single element to this buffer and return - * the identity of the buffer. + /** Add a single element to this collection and return + * the identity of the collection. * - * @param elem the element to append. + * @param elem the element to add. */ def +(elem: A): this.type = { this += elem; this } - /** Append two or more elements to this buffer and return - * the identity of the buffer. + /** Add two or more elements to this collection and return + * the identity of the collection. * - * @param elem1 the first element to append. - * @param elem2 the second element to append. - * @param elems the remaining elements to append. + * @param elem1 the first element to add. + * @param elem2 the second element to add. + * @param elems the remaining elements to add. */ def +(elem1: A, elem2: A, elems: A*): this.type = this + elem1 + elem2 ++ elems.asInstanceOf[Iterable[A]] // !@! - /** Appends a number of elements provided by an iterable object + /** Adds a number of elements provided by an iterable object * via its <code>elements</code> method. The identity of the - * buffer is returned. + * collection is returned. * * @param iter the iterable object. - * @return the updated buffer. + * @return the updated collection. */ def ++(iter: Iterable[A]): this.type = { this ++= iter; this } - /** Appends a number of elements provided by an iterator + /** Adds a number of elements provided by an iterator * via its <code>elements</code> method. The identity of the - * buffer is returned. + * collection is returned. * * @param iter the iterator - * @return the updated buffer. + * @return the updated collection. */ def ++(iter: Iterator[A]): this.type = { this ++= iter; this } - /** Clears the buffer contents. + /** Clears the collection contents. */ def clear() } diff --git a/src/library/scalax/collection/generic/mutable/Shrinkable.scala b/src/library/scalax/collection/generic/mutable/Shrinkable.scala new file mode 100644 index 0000000000..49e1b57eb6 --- /dev/null +++ b/src/library/scalax/collection/generic/mutable/Shrinkable.scala @@ -0,0 +1,82 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id: Iterable.scala 15188 2008-05-24 15:01:02Z stepancheg $ + +package scalax.collection.generic.mutable + +/** This class represents collections that can be shrunk using a -= operator. + * + * @autor Martin Odersky + * @owner Martin Odersky + * @version 2.8 + */ +trait Shrinkable[A] { + + /** Remove a single element from this collection. + * + * @param elem the element to append. + */ + def -=(elem: A): Unit + + /** Remove two or more elements from this collection. + * @param elem1 the first element. + * @param elem2 the second element. + * @param elems the remaining elements. + */ + def -= (elem1: A, elem2: A, elems: A*) { + this -= elem1 + this -= elem2 + this --= elems.asInstanceOf[Iterable[A]] // !@! + } + + /** Remove all the elements provided by an iterable + * <code>elems</code> from the collection. + */ + def --=(elems: Iterable[A]) { elems foreach -= } + + /** Remove all the elements provided by an iterator + * <code>elems</code> from the collection. + */ + def --=(elems: Iterator[A]) { elems foreach -= } + /** Remove a single element from the collection. + * @return the collection itself with the element removed. + * + * @param elem the element to be removed + */ + def - (elem: A): this.type = { -=(elem); this } + + /** Remove two or more elements from this collection. + * + * @param elem1 the first element. + * @param elem2 the second element. + * @param elems the remaining elements. + * @return the collection itself with the elements removed. + */ + def - (elem1: A, elem2: A, elems: A*): this.type = { -=(elem1, elem2, elems: _*); this } + + /** Remove all the elements provided by an iterator + * <code>elems</code> from the collection. + * + * @param elems An iterator containing the elements to remove from the collection. + * @return the collection itself with the elements removed. + */ + def -- (elems: Iterable[A]): this.type = { this --= elems; this } + + /** Remove all the elements provided by an iterator + * <code>elems</code> from the collection. + * + * @param elems An iterator containing the elements to remove from the collection. + * @return the collection itself with the elements removed. + */ + def -- (elems: Iterator[A]): this.type = { this --= elems; this } +} + + + + diff --git a/src/library/scalax/collection/generic/mutable/VectorTemplate.scala b/src/library/scalax/collection/generic/mutable/VectorTemplate.scala index b99600948a..4d748a79d1 100644 --- a/src/library/scalax/collection/generic/mutable/VectorTemplate.scala +++ b/src/library/scalax/collection/generic/mutable/VectorTemplate.scala @@ -44,10 +44,10 @@ self => */ override def view(from: Int, until: Int): VectorView[CC, A] = view.slice(from, until) - def readOnly: Sequence[A] = new collection.immutable.Vector[A] { //!!! + def readOnly: collection.Vector[A] = new collection.Vector[A] { //!!! just use a VectorProxy? def length = self.length def apply(idx : Int) = self.apply(idx) - def newBuilder[B]: Builder[CC, B] = self.newBuilder[B] + def newBuilder[B]: Builder[collection.Vector, B] = self.newBuilder[B] //mapResult (_.readOnly) override def foreach(f: A => Unit) = self.foreach(f) override def stringPrefix = self.stringPrefix+"RO" } diff --git a/src/library/scalax/collection/immutable/Iterable.scala b/src/library/scalax/collection/immutable/Iterable.scala index c299518d1b..07e1fed890 100644 --- a/src/library/scalax/collection/immutable/Iterable.scala +++ b/src/library/scalax/collection/immutable/Iterable.scala @@ -14,6 +14,7 @@ import generic.covariant * @version 2.8 */ trait Iterable[+A] extends collection.Iterable[A] + with covariant.IterableTemplate[Iterable, A] object Iterable extends covariant.IterableFactory[Iterable] { val empty: Iterable[Nothing] = Nil diff --git a/src/library/scalax/collection/immutable/OrderedIterable.scala b/src/library/scalax/collection/immutable/OrderedIterable.scala index 402244953d..1c3fb67fb2 100644 --- a/src/library/scalax/collection/immutable/OrderedIterable.scala +++ b/src/library/scalax/collection/immutable/OrderedIterable.scala @@ -13,7 +13,9 @@ import generic.covariant * @owner Martin Odersky * @version 2.8 */ -trait OrderedIterable[+A] extends collection.OrderedIterable[A] with Iterable[A] +trait OrderedIterable[+A] extends Iterable[A] + with covariant.OrderedIterableTemplate[OrderedIterable, A] + with collection.OrderedIterable[A] object OrderedIterable extends covariant.IterableFactory[OrderedIterable] { val empty: OrderedIterable[Nothing] = Nil diff --git a/src/library/scalax/collection/immutable/Sequence.scala b/src/library/scalax/collection/immutable/Sequence.scala index fdb9fadf04..10ae805106 100644 --- a/src/library/scalax/collection/immutable/Sequence.scala +++ b/src/library/scalax/collection/immutable/Sequence.scala @@ -9,11 +9,13 @@ import generic.covariant * @note If a collection has a known <code>size</code>, it should also sub-type <code>SizedIterable</code>. * * @author Matthias Zenger - * @autor Martin Odersky + * @autor Martin Oderskyter * @owner Martin Odersky * @version 2.8 */ -trait Sequence[+A] extends collection.Sequence[A] with OrderedIterable[A] +trait Sequence[+A] extends OrderedIterable[A] + with covariant.SequenceTemplate[Sequence, A] + with collection.Sequence[A] object Sequence extends covariant.SequenceFactory[Sequence] { val empty: Sequence[Nothing] = Nil diff --git a/src/library/scalax/collection/immutable/Set.scala b/src/library/scalax/collection/immutable/Set.scala new file mode 100755 index 0000000000..5b39aaa3a4 --- /dev/null +++ b/src/library/scalax/collection/immutable/Set.scala @@ -0,0 +1,43 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id: Set.scala 16893 2009-01-13 13:09:22Z cunei $ + + +package scalax.collection.immutable + +import collection.generic._ + +object Set extends generic.SetFactory[Set] { + private val hashSeed = "Set".hashCode + def empty[A]: Set[A] = null // !!! +} + +trait Set[A] extends OrderedIterable[A] + with collection.Set[A] + with SetTemplate[Set, A] { + + /** Compares this set with another object and returns true, iff the + * other object is also a set which contains the same elements as + * this set. + * + * @param that the other object + * @note not necessarily run-time type safe. + * @return <code>true</code> iff this set and the other set + * contain the same elements. + */ + override def equals(that: Any): Boolean = that match { + case other: Set[_] => + this.size == other.size && subsetOf(other.asInstanceOf[Set[A]]) + case _ => + false + } + + override def hashCode = (Set.hashSeed /: this)(_ * 41 + _.hashCode) + +} diff --git a/src/library/scalax/collection/immutable/Stream.scala b/src/library/scalax/collection/immutable/Stream.scala index 63333ff091..3581ac5b5d 100755 --- a/src/library/scalax/collection/immutable/Stream.scala +++ b/src/library/scalax/collection/immutable/Stream.scala @@ -416,7 +416,8 @@ import Stream._ * @author Martin Odersky, Matthias Zenger * @version 1.1 08/08/03 */ -abstract class Stream[+A] extends Sequence[A] with SequenceTemplate[Stream, A] { +abstract class Stream[+A] extends Sequence[A] + with SequenceTemplate[Stream, A] { self => import collection.{Iterable, OrderedIterable, Sequence, Vector} diff --git a/src/library/scalax/collection/immutable/Vector.scala b/src/library/scalax/collection/immutable/Vector.scala index 64cf512c90..3848304525 100644 --- a/src/library/scalax/collection/immutable/Vector.scala +++ b/src/library/scalax/collection/immutable/Vector.scala @@ -13,7 +13,9 @@ import generic.covariant * @owner Martin Odersky * @version 2.8 */ -trait Vector[+A] extends collection.Vector[A] with Sequence[A] +trait Vector[+A] extends Sequence[A] + with covariant.VectorTemplate[Vector, A] + with collection.Vector[A] object Vector extends covariant.SequenceFactory[Vector] { val empty: Vector[Nothing] = immutable.Vector.empty diff --git a/src/library/scalax/collection/mutable/Array.scala b/src/library/scalax/collection/mutable/Array.scala new file mode 100755 index 0000000000..c2b4d19101 --- /dev/null +++ b/src/library/scalax/collection/mutable/Array.scala @@ -0,0 +1,410 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2002-2009, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id: Array.scala 17000 2009-01-29 13:05:53Z odersky $ + + +package scalax.collection.mutable + +import scalax.collection.generic._ +import compat.Platform.arraycopy + +/** This object contains utility methods operating on arrays. + * + * @author Martin Odersky + * @version 1.0 + */ +object Array extends SequenceFactory[Array] { + + /** Copy one array to another. + * Equivalent to + * <code>System.arraycopy(src, srcPos, dest, destPos, length)</code>, + * except that this works also for polymorphic and boxed arrays. + * + * @param src ... + * @param srcPos ... + * @param dest ... + * @param destPos ... + * @param length ... + */ + def copy(src: AnyRef, srcPos: Int, dest: AnyRef, destPos: Int, length: Int) { + src match { + case xs: runtime.BoxedArray[_] => + xs.copyTo(srcPos, dest, destPos, length) + case _ => + dest match { + case xs: runtime.BoxedArray[_] => + xs.copyFrom(src, srcPos, destPos, length) + case _ => + def fillDest[T](da: Array[T], sa: Int=>T) { + var d = destPos + for (s <- srcPos to srcPos+length-1) { + da(d) = sa(s); d += 1 + } + } + if (dest.isInstanceOf[Array[Any]]) { + def fill(sa: Int=>Any) = fillDest(dest.asInstanceOf[Array[Any]], sa) + src match { + case sa:Array[Int] => fill(s=>Int.box(sa(s))) +/*!!! + case sa:Array[Long] => fill(s=>Long.box(sa(s))) + case sa:Array[Char] => fill(s=>Char.box(sa(s))) + case sa:Array[Boolean] => fill(s=>Boolean.box(sa(s))) + case sa:Array[Byte] => fill(s=>Byte.box(sa(s))) + case sa:Array[Short] => fill(s=>Short.box(sa(s))) + case sa:Array[Double] => fill(s=>Double.box(sa(s))) + case sa:Array[Float] => fill(s=>Float.box(sa(s))) +*/ + case _ => arraycopy(src, srcPos, dest, destPos, length) + } + } else if (dest.isInstanceOf[Array[AnyVal]]) { + def fill(sa: Int=>AnyVal) = fillDest(dest.asInstanceOf[Array[AnyVal]], sa) + src match { + case sa:Array[Int] => fill(sa(_)) +/*!!! + case sa:Array[Long] => fill(sa(_)) + case sa:Array[Char] => fill(sa(_)) + case sa:Array[Boolean] => fill(sa(_)) + case sa:Array[Byte] => fill(sa(_)) + case sa:Array[Short] => fill(sa(_)) + case sa:Array[Double] => fill(sa(_)) + case sa:Array[Float] => fill(sa(_)) +*/ + case _ => arraycopy(src, srcPos, dest, destPos, length) + } + } else + arraycopy(src, srcPos, dest, destPos, length) + } + } + } + + /** Concatenate all argument sequences into a single array. + * + * @param xs the given argument sequences + * @return the array created from the concatenated arguments + */ + def concat[T](xs: Seq[T]*): Array[T] = { + var len = 0 + for (x <- xs) len += x.length + val result = new Array[T](len) + var start = 0 + for (x <- xs) { + copy(x.toArray, 0, result, start, x.length) + start += x.length + } + result + } + + /** Create an array with given elements. + * + * @param xs the elements to put in the array + * @return the array containing elements xs. + */ + def apply[A](xs: A*): Array[A] = { + val array = new Array[A](xs.length) + var i = 0 + for (x <- xs.elements) { array(i) = x; i += 1 } + array + } +/*!!! enable when arrays in Scala + def apply(xs: Boolean*): Array[Boolean] = { + val array = new Array[Boolean](xs.length) + var i = 0 + for (x <- xs.elements) { array(i) = x; i += 1 } + array + } + + def apply(xs: Byte*): Array[Byte] = { + val array = new Array[Byte](xs.length) + var i = 0 + for (x <- xs.elements) { array(i) = x; i += 1 } + array + } + + def apply(xs: Short*): Array[Short] = { + val array = new Array[Short](xs.length) + var i = 0 + for (x <- xs.elements) { array(i) = x; i += 1 } + array + } + + def apply(xs: Char*): Array[Char] = { + val array = new Array[Char](xs.length) + var i = 0 + for (x <- xs.elements) { array(i) = x; i += 1 } + array + } + + def apply(xs: Int*): Array[Int] = { + val array = new Array[Int](xs.length) + var i = 0 + for (x <- xs.elements) { array(i) = x; i += 1 } + array + } + + def apply(xs: Long*): Array[Long] = { + val array = new Array[Long](xs.length) + var i = 0 + for (x <- xs.elements) { array(i) = x; i += 1 } + array + } + + def apply(xs: Float*): Array[Float] = { + val array = new Array[Float](xs.length) + var i = 0 + for (x <- xs.elements) { array(i) = x; i += 1 } + array + } + + def apply(xs: Double*): Array[Double] = { + val array = new Array[Double](xs.length) + var i = 0 + for (x <- xs.elements) { array(i) = x; i += 1 } + array + } + + def apply(xs: Unit*): Array[Unit] = { + val array = new Array[Unit](xs.length) + var i = 0 + for (x <- xs.elements) { array(i) = x; i += 1 } + array + } +*/ + /** Create an array containing several copies of an element. + * + * @param n the length of the resulting array + * @param elem the element composing the resulting array + * @return an array composed of n elements all equal to elem + * @deprecated use `Array.fill` instead. + */ + @deprecated def make[A](n: Int, elem: A): Array[A] = { + val a = new Array[A](n) + var i = 0 + while (i < n) { + a(i) = elem + i += 1 + } + a + } + + /** Create an array containing the values of a given function <code>f</code> + * over given range <code>[0..n)</code> + * @deprecated use `Array.tabulate` instead. + */ + @deprecated def fromFunction[A](f: Int => A)(n: Int): Array[A] = { + val a = new Array[A](n) + var i = 0 + while (i < n) { + a(i) = f(i) + i += 1 + } + a + } + + /** Create an array containing the values of a given function <code>f</code> + * over given range <code>[0..n1, 0..n2)</code> + * @deprecated use `Array.tabulate` instead. + */ + @deprecated def fromFunction[A](f: (Int, Int) => A)(n1: Int, n2: Int): Array[Array[A]] = + fromFunction(i => fromFunction(f(i, _))(n2))(n1) + + /** Create an array containing the values of a given function <code>f</code> + * over given range <code>[0..n1, 0..n2, 0..n3)</code> + * @deprecated use `Array.tabulate` instead. + */ + @deprecated def fromFunction[A](f: (Int, Int, Int) => A)(n1: Int, n2: Int, n3: Int): Array[Array[Array[A]]] = + fromFunction(i => fromFunction(f(i, _, _))(n2, n3))(n1) + + /** Create an array containing the values of a given function <code>f</code> + * over given range <code>[0..n1, 0..n2, 0..n3, 0..n4)</code> + * @deprecated use `Array.tabulate` instead. + */ + @deprecated def fromFunction[A](f: (Int, Int, Int, Int) => A)(n1: Int, n2: Int, n3: Int, n4: Int): Array[Array[Array[Array[A]]]] = + fromFunction(i => fromFunction(f(i, _, _, _))(n2, n3, n4))(n1) + + /** Create an array containing the values of a given function <code>f</code> + * over given range <code>[0..n1, 0..n2, 0..n3, 0..n4, 0..n5)</code> + * @deprecated use `Array.tabulate` instead. + */ + @deprecated def fromFunction[A](f: (Int, Int, Int, Int, Int) => A)(n1: Int, n2: Int, n3: Int, n4: Int, n5: Int): Array[Array[Array[Array[Array[A]]]]] = + fromFunction(i => fromFunction(f(i, _, _, _, _))(n2, n3, n4, n5))(n1) + + /** Create array with given dimensions */ + def ofDim[A](n1: Int): Array[A] = + new Array[A](n1) + def ofDim[A](n1: Int, n2: Int): Array[Array[A]] = + tabulate(n1)(_ => ofDim[A](n2)) + def ofDim[A](n1: Int, n2: Int, n3: Int): Array[Array[Array[A]]] = + tabulate(n1)(_ => ofDim[A](n2, n3)) + def ofDim[A](n1: Int, n2: Int, n3: Int, n4: Int): Array[Array[Array[Array[A]]]] = + tabulate(n1)(_ => ofDim[A](n2, n3, n4)) + def ofDim[A](n1: Int, n2: Int, n3: Int, n4: Int, n5: Int): Array[Array[Array[Array[Array[A]]]]] = + tabulate(n1)(_ => ofDim[A](n2, n3, n4, n5)) +} + +/** This class represents polymorphic arrays. <code>Array[T]</code> is Scala's representation + * for Java's <code>T[]</code>. + * + * @author Martin Odersky + * @version 1.0 + */ +final class Array[A](_length: Int) extends Vector[A] with mutable.VectorTemplate[Array, A] { + + /** Multidimensional array creation + * @deprecated use Array.ofDim instead + */ + @deprecated def this(dim1: Int, dim2: Int) = { + this(dim1) + throw new Error() + } + + /** Multidimensional array creation + * @deprecated use Array.ofDim instead */ + @deprecated def this(dim1: Int, dim2: Int, dim3: Int) = { + this(dim1) + throw new Error() + } + + /** Multidimensional array creation + * @deprecated use Array.ofDim instead */ + @deprecated def this(dim1: Int, dim2: Int, dim3: Int, dim4: Int) = { + this(dim1) + throw new Error() + } + + /** Multidimensional array creation + * @deprecated use Array.ofDim instead */ + @deprecated def this(dim1: Int, dim2: Int, dim3: Int, dim4: Int, dim5: Int) = { + this(dim1); + throw new Error() + } + + /** Multidimensional array creation + * @deprecated use Array.ofDim instead */ + @deprecated def this(dim1: Int, dim2: Int, dim3: Int, dim4: Int, dim5: Int, dim6: Int) = { + this(dim1) + throw new Error() + } + + /** Multidimensional array creation + * @deprecated use Array.ofDim instead */ + @deprecated def this(dim1: Int, dim2: Int, dim3: Int, dim4: Int, dim5: Int, dim6: Int, dim7: Int) = { + this(dim1) + throw new Error() + } + + /** Multidimensional array creation + * @deprecated use Array.ofDim instead */ + @deprecated def this(dim1: Int, dim2: Int, dim3: Int, dim4: Int, dim5: Int, dim6: Int, dim7: Int, dim8: Int) = { + this(dim1) + throw new Error() + } + + /** Multidimensional array creation + * @deprecated use Array.ofDim instead */ + @deprecated def this(dim1: Int, dim2: Int, dim3: Int, dim4: Int, dim5: Int, dim6: Int, dim7: Int, dim8: Int, dim9: Int) = { + this(dim1) + throw new Error() + } + + /** The length of the array */ + def length: Int = throw new Error() + + /** The element at given index. + * <p> + * Indices start a <code>0</code>; <code>xs.apply(0)</code> is the first + * element of array <code>xs</code>. + * </p> + * <p> + * Note the indexing syntax <code>xs(i)</code> is a shorthand for + * <code>xs.apply(i)</code>. + * </p> + * + * @param i the index + * @throws ArrayIndexOutOfBoundsException if <code>i < 0</code> or + * <code>length <= i</code> + */ + def apply(i: Int): A = throw new Error() + + /* Create a new array builder */ + def newBuilder[B]: Builder[Array, B] = throw new Error() + + /** <p> + * Update the element at given index. + * </p> + * <p> + * Indices start a <code>0</code>; <code>xs.apply(0)</code> is the first + * element of array <code>xs</code>. + * </p> + * <p> + * Note the indexing syntax <code>xs(i) = x</code> is a shorthand + * for <code>xs.update(i, x)</code>. + * </p> + * + * @param i the index + * @param x the value to be written at index <code>i</code> + * @throws ArrayIndexOutOfBoundsException if <code>i < 0</code> or + * <code>length <= i</code> + */ + override def update(i: Int, x: A) { throw new Error() } + + /** + * @return a deep string representation of this array. + */ + def deepToString(): String = throw new Error() + + /** <p> + * Returns a string representation of this array object. The resulting string + * begins with the string <code>start</code> and is finished by the string + * <code>end</code>. Inside, the string representations of elements (w.r.t. + * the method <code>deepToString()</code>) are separated by the string + * <code>sep</code>. For example: + * </p> + * <p> + * <code>Array(Array(1, 2), Array(3)).deepMkString("[", "; ", "]") = "[[1; 2]; [3]]"</code> + * </p> + * + * @param start starting string. + * @param sep separator string. + * @param end ending string. + * @return a string representation of this array object. + */ + def deepMkString(start: String, sep: String, end: String): String = + throw new Error() + + /** Returns a string representation of this array object. The string + * representations of elements (w.r.t. the method <code>deepToString()</code>) + * are separated by the string <code>sep</code>. + * + * @param sep separator string. + * @return a string representation of this array object. + */ + def deepMkString(sep: String): String = throw new Error() + + /** <p> + * Returns <code>true</code> if the two specified arrays are + * <em>deeply equal</em> to one another. + * </p> + * <p> + * Two array references are considered deeply equal if both are null, + * or if they refer to arrays that contain the same number of elements + * and all corresponding pairs of elements in the two arrays are deeply + * equal. + * </p> + * <p> + * See also method <code>deepEquals</code> in the Java class + * <a href="http://java.sun.com/javase/6/docs/api/java/util/Arrays.html" + * target="_top">java.utils.Arrays</a> + * </p> + * + * @param that the second + * @return <code>true</code> iff both arrays are deeply equal. + */ + def deepEquals(that: Any): Boolean = throw new Error() + +} diff --git a/src/library/scalax/collection/mutable/ArrayBuffer.scala b/src/library/scalax/collection/mutable/ArrayBuffer.scala index df7f6ba758..dbdb96e004 100644 --- a/src/library/scalax/collection/mutable/ArrayBuffer.scala +++ b/src/library/scalax/collection/mutable/ArrayBuffer.scala @@ -11,6 +11,13 @@ package scalax.collection.mutable +import generic.SequenceFactory + +/* Factory object for `ArrayBuffer` class */ +object ArrayBuffer extends SequenceFactory[ArrayBuffer] { + def apply[A](args: A*): ArrayBuffer[A] = new ArrayBuffer[A] ++ args.asInstanceOf[Iterable[A]] // !@! +} + /** An implementation of the <code>Buffer</code> class using an array to * represent the assembled sequence internally. Append, update and random * access take constant time (amortized time). Prepends and removes are @@ -21,7 +28,14 @@ package scalax.collection.mutable * @version 2.8 */ @serializable -class ArrayBuffer[A] extends Buffer[A] with Builder[ArrayBuffer, A] with ResizableArray[A] { +class ArrayBuffer[A](override protected val initialSize: Int) + extends Buffer[A] + with Vector[A] + with generic.mutable.VectorTemplate[ArrayBuffer, A] + with Builder[ArrayBuffer, A] + with ResizableArray[A] { + + def this() = this(16) def clear() { reduceToSize(0) } @@ -40,14 +54,14 @@ class ArrayBuffer[A] extends Buffer[A] with Builder[ArrayBuffer, A] with Resizab * via its <code>elements</code> method. The identity of the * buffer is returned. * - * @param iter the iterable object. + * @param iter the iterfable object. * @return the updated buffer. */ - override def ++=(iter: Iterable[A]) = iter match { - case v: Vector[A] => + override def ++=(iter: collection.Iterable[A]) = iter match { + case v: Vector[_] => val n = v.length ensureSize(size0 + n) - v.copyToArray(array.asInstanceOf[Array[Any]], n) + v.copyToArray(array.asInstanceOf[scala.Array[Any]], n) case _ => super.++=(iter) } @@ -91,7 +105,7 @@ class ArrayBuffer[A] extends Buffer[A] with Builder[ArrayBuffer, A] with Resizab val len = xs.length ensureSize(size0 + len) copy(n, n + len, size0 - n) - xs.copyToArray(array.asInstanceOf[Array[Any]], n) + xs.copyToArray(array.asInstanceOf[scala.Array[Any]], n) size0 += len } diff --git a/src/library/scalax/collection/mutable/Buffer.scala b/src/library/scalax/collection/mutable/Buffer.scala index 2a9eb263e9..502f99758a 100644 --- a/src/library/scalax/collection/mutable/Buffer.scala +++ b/src/library/scalax/collection/mutable/Buffer.scala @@ -11,7 +11,13 @@ package scalax.collection.mutable -import generic.mutable.VectorTemplate +import generic.{SequenceFactory, SequenceTemplate} +import generic.mutable.{Growable, Shrinkable} + +/* Factory object for `Buffer` trait */ +object Buffer extends SequenceFactory[Buffer] { + def apply[A](args: A*): Buffer[A] = ArrayBuffer.apply(args: _*) +} /** Buffers are used to create sequences of elements incrementally by * appending, prepending, or inserting new elements. It is also @@ -23,9 +29,12 @@ import generic.mutable.VectorTemplate * @version 2.8 */ @cloneable -trait Buffer[A] extends Vector[A] with VectorTemplate[Buffer, A] with Appendable[A] +trait Buffer[A] extends mutable.Sequence[A] + with SequenceTemplate[Buffer, A] + with Growable[A] + with Shrinkable[A] // with Scriptable[Message[(Location, A)]] - with CloneableCollection + with CloneableCollection { // Abstract methods from Vector: @@ -35,13 +44,6 @@ trait Buffer[A] extends Vector[A] with VectorTemplate[Buffer, A] with Appendable */ def apply(n: Int): A - /** Return number of elements in the buffer - */ - def length: Int - - /** Create a new buffer of the same kind as this one */ - def newBuilder[B]: Builder[Buffer, B] = new ArrayBuffer[B] - /** Replace element at index <code>n</code> with the new element * <code>newelem</code>. * @@ -51,6 +53,16 @@ trait Buffer[A] extends Vector[A] with VectorTemplate[Buffer, A] with Appendable */ def update(n: Int, newelem: A): Unit + /** Return number of elements in the buffer + */ + def length: Int + + /** Create a new buffer of the same kind as this one */ + def newBuilder[B]: Builder[Buffer, B] = new ArrayBuffer[B] + + override def newBuilder[B](sizeHint: Int): Builder[Buffer, B] = + new ArrayBuffer[B](sizeHint) + // Abstract methods from Appendable /** Append a single element to this buffer. @@ -111,14 +123,6 @@ trait Buffer[A] extends Vector[A] with VectorTemplate[Buffer, A] with Appendable if (i != -1) remove(i) } - /** Removes a single element from this buffer, at its first occurrence, - * and returns the identity of the buffer. - * If the buffer does not contain that element, it is unchanged - * - * @param x the element to remove. - */ - def - (x: A): this.type = { -=(x); this } - /** Prepend two ore more elements to this buffer and return * the identity of the buffer. * @param elem the element to prepend. diff --git a/src/library/scalax/collection/mutable/Iterable.scala b/src/library/scalax/collection/mutable/Iterable.scala new file mode 100755 index 0000000000..0872c3c549 --- /dev/null +++ b/src/library/scalax/collection/mutable/Iterable.scala @@ -0,0 +1,32 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2008, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id: Iterable.scala 15188 2008-05-24 15:01:02Z stepancheg $ + +package scalax.collection.mutable + +import generic._ + +/** Collection classes mixing in this class provide a method + * <code>elements</code> which returns an iterator over all the + * elements contained in the collection. + * + * @note If a collection has a known <code>size</code>, it should also sub-type <code>SizedIterable</code>. + * + * @author Matthias Zenger + * @autor Martin Odersky + * @owner Martin Odersky + * @version 2.8 + */ +trait Iterable[A] extends collection.Iterable[A] with IterableTemplate[Iterable, A] + +/* Factory object for `Iterable` class */ +object Iterable extends IterableFactory[Iterable] { + /** The empty iterable */ + def apply[A](args: A*): Iterable[A] = ArrayBuffer.apply(args: _*) // !!! swicth to Array? +} diff --git a/src/library/scalax/collection/mutable/ListBuffer.scala b/src/library/scalax/collection/mutable/ListBuffer.scala index 3b7587d6d2..dff29f6453 100644 --- a/src/library/scalax/collection/mutable/ListBuffer.scala +++ b/src/library/scalax/collection/mutable/ListBuffer.scala @@ -11,10 +11,15 @@ package scalax.collection.mutable -import generic.SequenceForwarder +import generic.{SequenceForwarder, SequenceFactory, SequenceTemplate} import immutable.List import collection.immutable.{List, Nil, ::} +/* Factory object for `ListBuffer` class */ +object ListBuffer extends SequenceFactory[ListBuffer] { + def apply[A](args: A*): ListBuffer[A] = new ListBuffer[A] +} + /** A Buffer implementation back up by a list. It provides constant time * prepend and append. Most other operations are linear. * @@ -25,9 +30,12 @@ import collection.immutable.{List, Nil, ::} @serializable final class ListBuffer[A] extends Buffer[A] + with SequenceTemplate[ListBuffer, A] with Builder[List, A] with SequenceForwarder[A] { + import collection.immutable.Sequence + private var start: List[A] = Nil private var last0: ::[A] = _ private var exported: Boolean = false @@ -178,8 +186,7 @@ final class ListBuffer[A] } catch { case ex: Exception => throw new IndexOutOfBoundsException(n.toString()) - } - } + } } // Implementation of abstract method in Builder @@ -258,7 +265,7 @@ final class ListBuffer[A] } /** expose the underlying list but do not mark it as exported */ - override def readOnly : List[A] = start + def readOnly: List[A] = start // Private methods diff --git a/src/library/scalax/collection/mutable/OrderedIterable.scala b/src/library/scalax/collection/mutable/OrderedIterable.scala new file mode 100755 index 0000000000..90ef8018c7 --- /dev/null +++ b/src/library/scalax/collection/mutable/OrderedIterable.scala @@ -0,0 +1,22 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2008, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id: Iterable.scala 15188 2008-05-24 15:01:02Z stepancheg $ + +package scalax.collection.mutable + +import generic._ + +trait OrderedIterable[A] extends Iterable[A] with collection.OrderedIterable[A] with OrderedIterableTemplate[OrderedIterable, A] + +/* Factory object for `OrderedIterable` class */ +object OrderedIterable extends IterableFactory[OrderedIterable] { + /** The empty iterable */ + def apply[A](args: A*): OrderedIterable[A] = ArrayBuffer.apply(args: _*) // !!! swicth to Array? +} + diff --git a/src/library/scalax/collection/mutable/ResizableArray.scala b/src/library/scalax/collection/mutable/ResizableArray.scala index 93a4c7753a..11c3659712 100644 --- a/src/library/scalax/collection/mutable/ResizableArray.scala +++ b/src/library/scalax/collection/mutable/ResizableArray.scala @@ -19,6 +19,8 @@ package scalax.collection.mutable */ trait ResizableArray[A] extends Vector[A] { + import scala.Array // !!! + protected def initialSize: Int = 16 protected var array: Array[AnyRef] = new Array[AnyRef](initialSize min 1) diff --git a/src/library/scalax/collection/mutable/BuilderProxy.scala b/src/library/scalax/collection/mutable/Sequence.scala index cf5b3d69a5..c4d72231d5 100644..100755 --- a/src/library/scalax/collection/mutable/BuilderProxy.scala +++ b/src/library/scalax/collection/mutable/Sequence.scala @@ -1,22 +1,23 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2007, LAMP/EPFL ** +** / __/ __// _ | / / / _ | (c) 2003-2008, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** \* */ -// $Id: ListBuffer.scala 14378 2008-03-13 11:39:05Z dragos $ +// $Id: Iterable.scala 15188 2008-05-24 15:01:02Z stepancheg $ package scalax.collection.mutable -abstract class BuilderProxy[+CC[B], A] extends Builder[CC, A] with Proxy { - val self: Builder[DD, A] forSome { type DD[X] } - def +=(x: A) = self += x - def elements: Iterator[A] = self.elements - def result: CC[A] - def clear() = self.clear() - override def ++=(xs: Iterator[A]) = self ++= xs - override def ++=(xs: Iterable[A]) = self ++= xs +import generic._ + +trait Sequence[A] extends OrderedIterable[A] with collection.Sequence[A] with SequenceTemplate[Sequence, A] + +/* Factory object for `Sequence` class */ +object Sequence extends SequenceFactory[Sequence] { + /** The empty sequence */ + def apply[A](args: A*): Sequence[A] = ArrayBuffer.apply(args: _*) // !!! swicth to Array? } + diff --git a/src/library/scalax/collection/mutable/Set.scala b/src/library/scalax/collection/mutable/Set.scala new file mode 100644 index 0000000000..40dc643012 --- /dev/null +++ b/src/library/scalax/collection/mutable/Set.scala @@ -0,0 +1,119 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id: Set.scala 16893 2009-01-13 13:09:22Z cunei $ + + +package scalax.collection.mutable + +import collection.generic._ +import collection.generic.mutable.{Growable, Shrinkable} + +/** The canonical factory methods for <a href="Set.html">mutable sets</a>. + * Currently these return <a href="HashSet.html">HashSet's</a>. + */ +object Set extends generic.SetFactory[Set] { + /** The empty map of this type; this is implemented as a hashtable */ + def empty[A]: Set[A] = null // !!! new HashSet[A] +} + +/** This class represents mutable sets. Concrete set implementations + * just have to provide functionality for the abstract methods in + * <a href="../Set.html" target="contentFrame"> + * <code>scala.collection.Set</code></a> as well as for <code>+=</code>, + * <code>-= and <code>clear</code>. + * + * @author Matthias Zenger + * @author Martin Odersky + * @version 2.8 + */ +@cloneable +trait Set[A] extends OrderedIterable[A] + with collection.Set[A] + with SetTemplate[Set, A] + with Growable[A] + with Shrinkable[A] + with Cloneable[A] { +self => + + /** This method allows one to add or remove an element <code>elem</code> + * from this set depending on the value of parameter <code>included</code>. + * Typically, one would use the following syntax: + * <pre>set(elem) = true</pre> + * + */ + def update(elem: A, included: Boolean) { + if (included) this += elem else this -= elem + } + + /** Add a new element to the set. + * + * @param elem the element to be added + */ + def +=(elem: A) + + /** Removes a single element from a set. + * @param elem The element to be removed. + */ + def -=(elem: A) + + // Bridge methods to methods in Growable/Shrinkable; + // we can't directly inherit these because they override nothing. + + override def - (elem: A): this.type = super.-(elem) + override def - (elem1: A, elem2: A, elems: A*): this.type = super.-(elem1, elem2, elems: _*) + override def -- (elems: collection.Iterable[A]): this.type = super.--(elems) + override def -- (elems: Iterator[A]): this.type = super.--(elems) + + override def + (elem: A): this.type = super.+(elem) + override def + (elem1: A, elem2: A, elems: A*): this.type = super.+(elem1, elem2, elems: _*) + override def ++ (elems: collection.Iterable[A]): this.type = super.++(elems) + override def ++ (elems: Iterator[A]): this.type = super.++(elems) + + /** This method computes an intersection with set <code>that</code>. + * It removes all the elements that are not present in <code>that</code>. + * + * @param that the set to intersect with. + */ + def intersect(that: Set[A]) { retain(that.contains) } + + /** Method <code>retain removes all elements from the set for + * which the predicate <code>p</code> yields the value <code>false</code>. + */ + def retain(p: A => Boolean): Unit = foreach (elem => if (!p(elem)) -=(elem)) + + /** Removes all elements from the set. After this operation is completed, + * the set will be empty. + */ + def clear() { elements foreach -= } + + /** Send a message to this scriptable object. + * + * @param cmd the message to send. + * @throws <code>Predef.UnsupportedOperationException</code> + * if the message was not understood. + def <<(cmd: Message[A]): Unit = cmd match { + case Include(elem) => this += elem + case Remove(elem) => this -= elem + case Reset() => clear + case s: Script[_] => s.elements foreach << + case _ => throw new UnsupportedOperationException("message " + cmd + " not understood") + } + */ + + /** Return a read-only projection of this set !!! just us an (immutable) setProxy? */ + def readOnly : collection.Set[A] = new collection.Set[A] { + def contains(item : A) = Set.this.contains(item) + override def size = self.size + override def +(elem: A) = self + elem + override def -(elem: A) = self - elem + override def elements = self.elements + override def foreach(f: A => Unit) = self.foreach(f) + override def newBuilder[B]: Builder[collection.Set, B] = self.newBuilder[B] + } +} diff --git a/src/library/scalax/collection/mutable/StringBuilder.scala b/src/library/scalax/collection/mutable/StringBuilder.scala index 10fc47ff04..3152182dc4 100755 --- a/src/library/scalax/collection/mutable/StringBuilder.scala +++ b/src/library/scalax/collection/mutable/StringBuilder.scala @@ -12,8 +12,10 @@ package scalax.collection.mutable import scalax.collection.generic._ +import scalax.collection.generic.mutable.Growable import scalax.runtime._ + /** <p> * A mutable sequence of characters. This class provides an API compatible * with <a class="java/lang/StringBuilder" href="" target="_top"> @@ -27,9 +29,13 @@ import scalax.runtime._ @serializable @SerialVersionUID(0 - 8525408645367278351L) final class StringBuilder(initCapacity: Int, private val initValue: String) - extends PartialFunction[Int, Char] with Appendable[Any] with java.lang.CharSequence { + extends PartialFunction[Int, Char] + with Growable[Any] + with java.lang.CharSequence { require(initCapacity > 0) + type Array[T] = scala.Array[T] // !!! + /** The value is used for character storage. */ private var array = new Array[Char](initCapacity + initValue.length) @@ -850,6 +856,8 @@ final class StringBuilder(initCapacity: Int, private val initValue: String) object StringBuilder { + type Array[T] = scala.Array[T] // !!! + private val MIN_HIGH_SURROGATE = '\uD800' private val MAX_HIGH_SURROGATE = '\uDBFF' diff --git a/src/library/scalax/collection/mutable/Vector.scala b/src/library/scalax/collection/mutable/Vector.scala index 5569bfa283..aef1c75d94 100644 --- a/src/library/scalax/collection/mutable/Vector.scala +++ b/src/library/scalax/collection/mutable/Vector.scala @@ -10,11 +10,12 @@ package scalax.collection.mutable -trait Vector[A] extends collection.Vector[A] with generic.mutable.VectorTemplate[Vector, A] +import generic._ -object Vector extends generic.SequenceFactory[Vector] { - - /** The empty iterable */ - def apply[A](args: A*): Vector[A] = new ArrayBuffer[A] ++ args.asInstanceOf[Iterable[A]] // !@! +trait Vector[A] extends Sequence[A] with collection.Vector[A] with generic.mutable.VectorTemplate[Vector, A] +/* Factory object for `Vector` class */ +object Vector extends SequenceFactory[Vector] { + /** The empty vector */ + def apply[A](args: A*): Vector[A] = ArrayBuffer.apply(args: _*) // !!! swicth to Array? } diff --git a/src/library/scalax/runtime/Boxed.scala b/src/library/scalax/runtime/Boxed.scala index ace7c73753..241b12e485 100644 --- a/src/library/scalax/runtime/Boxed.scala +++ b/src/library/scalax/runtime/Boxed.scala @@ -11,9 +11,7 @@ package scalax.runtime -trait Boxed[T] { - - def unbox: T +trait Boxed { } diff --git a/src/library/scalax/runtime/BoxedAnyArray.scala b/src/library/scalax/runtime/BoxedAnyArray.scala new file mode 100755 index 0000000000..6e14cafdfc --- /dev/null +++ b/src/library/scalax/runtime/BoxedAnyArray.scala @@ -0,0 +1,239 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2002-2009, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id: BoxedAnyArray.scala 17000 2009-01-29 13:05:53Z odersky $ + + +package scalax.runtime + +import compat.Platform + +/** + * Arrays created by <code>new Array[T](length)</code> where <code>T</code> + * is a type variable. + * + * @author Martin Odersky + */ +@serializable +final class BoxedAnyArray[A](val length: Int) extends BoxedArray[A] { + + private var boxed = new Array[AnyRef](length) + private val hash = boxed.hashCode() + private var unboxed: AnyRef = null + private var elemClass: Class[_] = null + + def apply(index: Int): A = synchronized { + if (unboxed eq null) + boxed(index) + else if (elemClass eq classOf[Int]) + Int.box(unboxed.asInstanceOf[Array[Int]](index)) + else if (elemClass eq classOf[Double]) + Double.box(unboxed.asInstanceOf[Array[Double]](index)) + else if (elemClass eq classOf[Float]) + Float.box(unboxed.asInstanceOf[Array[Float]](index)) + else if (elemClass eq classOf[Long]) + Long.box(unboxed.asInstanceOf[Array[Long]](index)) + else if (elemClass eq classOf[Char]) + Char.box(unboxed.asInstanceOf[Array[Char]](index)) + else if (elemClass eq classOf[Byte]) + Byte.box(unboxed.asInstanceOf[Array[Byte]](index)) + else if (elemClass eq classOf[Short]) + Short.box(unboxed.asInstanceOf[Array[Short]](index)) + else if (elemClass eq classOf[Boolean]) + Boolean.box(unboxed.asInstanceOf[Array[Boolean]](index)) + else + unboxed.asInstanceOf[Array[AnyRef]](index) + }.asInstanceOf[A] + + def update(index: Int, _elem: A): Unit = synchronized { + val elem = _elem.asInstanceOf[AnyRef] + if (unboxed eq null) + boxed(index) = elem + else if (elemClass eq classOf[Int]) + unboxed.asInstanceOf[Array[Int]](index) = Int.unbox(elem) + else if (elemClass eq classOf[Double]) + unboxed.asInstanceOf[Array[Double]](index) = Double.unbox(elem) + else if (elemClass eq classOf[Float]) + unboxed.asInstanceOf[Array[Float]](index) = Float.unbox(elem) + else if (elemClass eq classOf[Long]) + unboxed.asInstanceOf[Array[Long]](index) = Long.unbox(elem) + else if (elemClass eq classOf[Char]) + unboxed.asInstanceOf[Array[Char]](index) = Char.unbox(elem) + else if (elemClass eq classOf[Byte]) + unboxed.asInstanceOf[Array[Byte]](index) = Byte.unbox(elem) + else if (elemClass eq classOf[Short]) + unboxed.asInstanceOf[Array[Short]](index) = Short.unbox(elem) + else if (elemClass eq classOf[Boolean]) + unboxed.asInstanceOf[Array[Boolean]](index) = Boolean.unbox(elem) + else + unboxed.asInstanceOf[Array[AnyRef]](index) = elem + } + + def unbox(elemClass: Class[_]): AnyRef = synchronized { + if (unboxed eq null) { + this.elemClass = elemClass; + if (elemClass eq classOf[Int]) { + val newvalue = new Array[Int](length) + var i = 0 + while (i < length) { + newvalue(i) = Int.unbox(boxed(i)) + i += 1 + } + unboxed = newvalue + } else if (elemClass eq classOf[Double]) { + val newvalue = new Array[Double](length) + var i = 0 + while (i < length) { + newvalue(i) = Double.unbox(boxed(i)) + i += 1 + } + unboxed = newvalue; + } else if (elemClass eq classOf[Float]) { + val newvalue = new Array[Float](length) + var i = 0 + while (i < length) { + newvalue(i) = Float.unbox(boxed(i)) + i += 1 + } + unboxed = newvalue; + } else if (elemClass eq classOf[Long]) { + val newvalue = new Array[Long](length) + var i = 0 + while (i < length) { + newvalue(i) = Long.unbox(boxed(i)) + i += 1 + } + unboxed = newvalue; + } else if (elemClass eq classOf[Char]) { + val newvalue = new Array[Char](length) + var i = 0 + while (i < length) { + newvalue(i) = Char.unbox(boxed(i)) + i += 1 + } + unboxed = newvalue + } else if (elemClass eq classOf[Byte]) { + val newvalue = new Array[Byte](length) + var i = 0 + while (i < length) { + newvalue(i) = Byte.unbox(boxed(i)) + i += 1 + } + unboxed = newvalue; + } else if (elemClass eq classOf[Short]) { + val newvalue = new Array[Short](length) + var i = 0 + while (i < length) { + newvalue(i) = Short.unbox(boxed(i)) + i += 1 + } + unboxed = newvalue; + } else if (elemClass eq classOf[Boolean]) { + val newvalue = new Array[Boolean](length) + var i = 0 + while (i < length) { + newvalue(i) = Boolean.unbox(boxed(i)) + i += 1 + } + unboxed = newvalue; + } else if (elemClass == classOf[AnyRef]) { + unboxed = boxed + } else { + unboxed = Platform.createArray(elemClass, length) + if (elemClass.isArray) { + var i = 0 + while (i < length) { + boxed(i) match { + case ba: BoxedArray[_] => boxed(i) = ba.unbox(elemClass.getComponentType()) + case _ => + } + i += 1 + } + } + Platform.arraycopy(boxed, 0, unboxed, 0, length) + } + boxed = null + } + unboxed + } + + override def equals(other: Any): Boolean = + other.isInstanceOf[BoxedAnyArray[_]] && (this eq (other.asInstanceOf[BoxedAnyArray[_]])) || + (if (unboxed eq null) boxed == other else unboxed == other) + + override def hashCode(): Int = hash + + def value: AnyRef = { + if (unboxed eq null) throw new NotDefinedError("BoxedAnyArray.value") + unboxed + } + + private def adapt(other: AnyRef): AnyRef = + if (this.unboxed eq null) + other match { + case that: BoxedAnyArray[_] => + if (that.unboxed eq null) { + that.boxed + } else { + if (ScalaRunTime.isValueClass(that.elemClass)) unbox(that.elemClass); + that.unboxed + } + case that: BoxedArray[_] => + adapt(that.value) + case that: Array[Int] => + unbox(classOf[Int]); that + case that: Array[Double] => + unbox(classOf[Double]); that + case that: Array[Float] => + unbox(classOf[Float]); that + case that: Array[Long] => + unbox(classOf[Long]); that + case that: Array[Char] => + unbox(classOf[Char]); that + case that: Array[Short] => + unbox(classOf[Short]); that + case that: Array[Byte] => + unbox(classOf[Byte]); that + case that: Array[Boolean] => + unbox(classOf[Boolean]); that + case _ => + other + } + else + other match { + case that: BoxedAnyArray[_] => + if (that.unboxed ne null) that.unboxed + else if (ScalaRunTime.isValueClass(this.elemClass)) that.unbox(this.elemClass) + else that.boxed + case that: BoxedArray[_] => + adapt(that.value) + case _ => + other + } + + override def copyFrom(src: AnyRef, from: Int, to: Int, len: Int) { + val src1 = adapt(src) + Array.copy(src1, from, if (unboxed ne null) unboxed else boxed, to, len) + } + + override def copyTo(from: Int, dest: AnyRef, to: Int, len: Int) { + var dest1 = adapt(dest) + Array.copy(if (unboxed ne null) unboxed else boxed, from, dest1, to, len) + } + + final override def filter(p: A => Boolean): BoxedArray[A] = { + val (len, include) = countAndMemo(p) + val result = new BoxedAnyArray[A](len) + var i, j = 0 + while (j < len) { + if (include(i)) { result(j) = this(i); j += 1 } + i += 1 + } + result + } +} diff --git a/src/library/scalax/runtime/BoxedArray.scala b/src/library/scalax/runtime/BoxedArray.scala new file mode 100755 index 0000000000..388d652882 --- /dev/null +++ b/src/library/scalax/runtime/BoxedArray.scala @@ -0,0 +1,138 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2002-2009, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id: BoxedArray.scala 17000 2009-01-29 13:05:53Z odersky $ + + +package scalax.runtime + +import Predef._ +import collection.mutable.{Vector, ArrayBuffer} +import collection.generic._ + +/** + * <p>A class representing <code>Array[T]</code></p> + * + * @author Martin Odersky, Stephane Micheloud + * @version 1.0 + */ +abstract class BoxedArray[A] extends Vector[A] with mutable.VectorTemplate[BoxedArray, A] with Boxed { + + /** The length of the array */ + def length: Int + + /** The element at given index */ + def apply(index: Int): A + + /** Update element at given index */ + def update(index: Int, elem: A): Unit + + /** Creates new builder for this collection ==> move to subclasses + * + * */ + def newBuilder[B] = new ArrayBuffer[B].mapResult[BoxedArray] { // !!! Adriaan: can't drop [BoxedArray] here + _.toArray.asInstanceOf[BoxedArray[B]] + } + + /** Convert to Java array. + * @param elemTag Either one of the tags ".N" where N is the name of a primitive type + * (@see ScalaRunTime), or a full class name. + */ + def unbox(elemClass: Class[_]): AnyRef + + /** The underlying array value + */ + def value: AnyRef + + def copyFrom(src: AnyRef, from: Int, to: Int, len: Int): Unit = + Array.copy(src, from, value, to, len) + + def copyTo(from: Int, dest: AnyRef, to: Int, len: Int): Unit = { + Array.copy(value, from, dest, to, len) + } + + override def equals(other: Any) = + (value == other) || + other.isInstanceOf[BoxedArray[_]] && (value == other.asInstanceOf[BoxedArray[_]].value) + + override def hashCode(): Int = value.hashCode() + + /** Fills the given array <code>xs</code> with the elements of + * this sequence starting at position <code>start</code>. + * + * @param xs the array to fill. + * @param start starting index. + * @pre the array must be large enough to hold all elements. + */ + override def copyToArray[B](xs: Array[B], start: Int, len: Int): Unit = + copyTo(0, xs, start, len) + + final def deepToString() = deepMkString(stringPrefix + "(", ", ", ")") + + final def deepMkString(start: String, sep: String, end: String): String = { + def _deepToString(x: Any) = x match { + case a: AnyRef if ScalaRunTime.isArray(a) => + ScalaRunTime.boxArray(a).deepMkString(start, sep, end) + case _ => + ScalaRunTime.stringOf(x) + } + val buf = new StringBuilder() + buf.append(start) + val elems = elements + if (elems.hasNext) buf.append(_deepToString(elems.next)) + while (elems.hasNext) { + buf.append(sep); buf.append(_deepToString(elems.next)) + } + buf.append(end) + buf.toString + } + + final def deepMkString(sep: String): String = this.deepMkString("", sep, "") + + final def deepEquals(that: Any): Boolean = { + def _deepEquals(x1: Any, x2: Any) = (x1, x2) match { + case (a1: BoxedArray[_], a2: BoxedArray[_]) => + _sameElements(a1, a2) + case (a1: AnyRef, a2: AnyRef) + if ScalaRunTime.isArray(a1) && ScalaRunTime.isArray(a2) => + _sameElements(ScalaRunTime.boxArray(a1), ScalaRunTime.boxArray(a2)) + case _ => + x1.equals(x2) + } + def _sameElements(a1: BoxedArray[_], a2: BoxedArray[_]): Boolean = { + val it1 = a1.elements + val it2 = a2.elements + var res = true + while (res && it1.hasNext && it2.hasNext) + res = _deepEquals(it1.next, it2.next) + !it1.hasNext && !it2.hasNext && res + } + that match { + case a: BoxedArray[_] => + _sameElements(this, a) + case a: AnyRef if ScalaRunTime.isArray(a) => + _sameElements(this, ScalaRunTime.boxArray(a)) + case _ => + false + } + } + + override final def stringPrefix: String = "Array" + + protected def countAndMemo(p: A => Boolean): (Int, Array[Boolean]) = { + val len = length + val memo = new Array[Boolean](len) + var count = 0 + var i = 0 + while (i < len) { + if (p(this(i))) { memo(i) = true; count += 1 } + i += 1 + } + (count, memo) + } +} diff --git a/src/library/scalax/runtime/BoxedBooleanArray.scala b/src/library/scalax/runtime/BoxedBooleanArray.scala new file mode 100755 index 0000000000..1dc136a50f --- /dev/null +++ b/src/library/scalax/runtime/BoxedBooleanArray.scala @@ -0,0 +1,25 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2002-2009, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id: BoxedByteArray.scala 17000 2009-01-29 13:05:53Z odersky $ + + +package scalax.runtime + +@serializable +final class BoxedBooleanArray(val value: Array[Boolean]) extends BoxedArray[Boolean] { + + def length: Int = value.length + + def apply(index: Int): Boolean = value(index) + + def update(index: Int, elem: Boolean) { + value(index) = elem + } + def unbox(elemClass: Class[_]): AnyRef = value +} diff --git a/src/library/scalax/runtime/BoxedByteArray.scala b/src/library/scalax/runtime/BoxedByteArray.scala new file mode 100755 index 0000000000..f42dbdda38 --- /dev/null +++ b/src/library/scalax/runtime/BoxedByteArray.scala @@ -0,0 +1,25 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2002-2009, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id: BoxedByteArray.scala 17000 2009-01-29 13:05:53Z odersky $ + + +package scalax.runtime + +@serializable +final class BoxedByteArray(val value: Array[Byte]) extends BoxedArray[Byte] { + + def length: Int = value.length + + def apply(index: Int): Byte = value(index) + + def update(index: Int, elem: Byte) { + value(index) = elem + } + def unbox(elemClass: Class[_]): AnyRef = value +} diff --git a/src/library/scalax/runtime/BoxedCharArray.scala b/src/library/scalax/runtime/BoxedCharArray.scala new file mode 100755 index 0000000000..c6f19d26e0 --- /dev/null +++ b/src/library/scalax/runtime/BoxedCharArray.scala @@ -0,0 +1,25 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2002-2009, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id: BoxedByteArray.scala 17000 2009-01-29 13:05:53Z odersky $ + + +package scalax.runtime + +@serializable +final class BoxedCharArray(val value: Array[Char]) extends BoxedArray[Char] { + + def length: Int = value.length + + def apply(index: Int): Char = value(index) + + def update(index: Int, elem: Char) { + value(index) = elem + } + def unbox(elemClass: Class[_]): AnyRef = value +} diff --git a/src/library/scalax/runtime/BoxedDoubleArray.scala b/src/library/scalax/runtime/BoxedDoubleArray.scala new file mode 100755 index 0000000000..16fc3e1056 --- /dev/null +++ b/src/library/scalax/runtime/BoxedDoubleArray.scala @@ -0,0 +1,25 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2002-2009, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id: BoxedByteArray.scala 17000 2009-01-29 13:05:53Z odersky $ + + +package scalax.runtime + +@serializable +final class BoxedDoubleArray(val value: Array[Double]) extends BoxedArray[Double] { + + def length: Int = value.length + + def apply(index: Int): Double = value(index) + + def update(index: Int, elem: Double) { + value(index) = elem + } + def unbox(elemClass: Class[_]): AnyRef = value +} diff --git a/src/library/scalax/runtime/BoxedFloatArray.scala b/src/library/scalax/runtime/BoxedFloatArray.scala new file mode 100755 index 0000000000..d10f16f6f6 --- /dev/null +++ b/src/library/scalax/runtime/BoxedFloatArray.scala @@ -0,0 +1,25 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2002-2009, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id: BoxedByteArray.scala 17000 2009-01-29 13:05:53Z odersky $ + + +package scalax.runtime + +@serializable +final class BoxedFloatArray(val value: Array[Float]) extends BoxedArray[Float] { + + def length: Int = value.length + + def apply(index: Int): Float = value(index) + + def update(index: Int, elem: Float) { + value(index) = elem + } + def unbox(elemClass: Class[_]): AnyRef = value +} diff --git a/src/library/scalax/runtime/BoxedIntArray.scala b/src/library/scalax/runtime/BoxedIntArray.scala new file mode 100755 index 0000000000..78a033190a --- /dev/null +++ b/src/library/scalax/runtime/BoxedIntArray.scala @@ -0,0 +1,25 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2002-2009, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id: BoxedByteArray.scala 17000 2009-01-29 13:05:53Z odersky $ + + +package scalax.runtime + +@serializable +final class BoxedIntArray(val value: Array[Int]) extends BoxedArray[Int] { + + def length: Int = value.length + + def apply(index: Int): Int = value(index) + + def update(index: Int, elem: Int) { + value(index) = elem + } + def unbox(elemClass: Class[_]): AnyRef = value +} diff --git a/src/library/scalax/runtime/BoxedLongArray.scala b/src/library/scalax/runtime/BoxedLongArray.scala new file mode 100755 index 0000000000..86816d6638 --- /dev/null +++ b/src/library/scalax/runtime/BoxedLongArray.scala @@ -0,0 +1,25 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2002-2009, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id: BoxedByteArray.scala 17000 2009-01-29 13:05:53Z odersky $ + + +package scalax.runtime + +@serializable +final class BoxedLongArray(val value: Array[Long]) extends BoxedArray[Long] { + + def length: Int = value.length + + def apply(index: Int): Long = value(index) + + def update(index: Int, elem: Long) { + value(index) = elem + } + def unbox(elemClass: Class[_]): AnyRef = value +} diff --git a/src/library/scalax/runtime/BoxedShortArray.scala b/src/library/scalax/runtime/BoxedShortArray.scala new file mode 100755 index 0000000000..6d5c82e7ba --- /dev/null +++ b/src/library/scalax/runtime/BoxedShortArray.scala @@ -0,0 +1,25 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2002-2009, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id: BoxedByteArray.scala 17000 2009-01-29 13:05:53Z odersky $ + + +package scalax.runtime + +@serializable +final class BoxedShortArray(val value: Array[Short]) extends BoxedArray[Short] { + + def length: Int = value.length + + def apply(index: Int): Short = value(index) + + def update(index: Int, elem: Short) { + value(index) = elem + } + def unbox(elemClass: Class[_]): AnyRef = value +} diff --git a/src/library/scalax/runtime/ScalaRunTime.scala b/src/library/scalax/runtime/ScalaRunTime.scala new file mode 100755 index 0000000000..0c8416be89 --- /dev/null +++ b/src/library/scalax/runtime/ScalaRunTime.scala @@ -0,0 +1,152 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2002-2009, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id: ScalaRunTime.scala 17000 2009-01-29 13:05:53Z odersky $ + + +package scalax.runtime + +/* The object <code>ScalaRunTime</code> provides ... + */ +object ScalaRunTime { + + def isArray(x: AnyRef): Boolean = (x != null && x.getClass.isArray) || (x != null && x.isInstanceOf[BoxedArray[_]]) + def isValueClass(clazz: Class[_]) = clazz.isPrimitive() + + def forceBoxedArray[A <: Any](xs: Seq[A]): Array[A] = { + val array = new Array[A](xs.length) + var i = 0 + for (x <- xs.elements) { array(i) = x; i += 1 } + array + } + + def checkInitialized[T <: AnyRef](x: T): T = + if (x == null) throw new UninitializedError else x + + abstract class Try[a] { + def Catch[b >: a](handler: PartialFunction[Throwable, b]): b + def Finally(handler: Unit): a + } + + def Try[a](block: => a): Try[a] = new Try[a] with Runnable { + var result: a = _ + var exception: Throwable = scala.runtime.ExceptionHandling.tryCatch(this) + + def run(): Unit = result = block + + def Catch[b >: a](handler: PartialFunction[Throwable, b]): b = + if (exception eq null) + result.asInstanceOf[b] + // !!! else if (exception is LocalReturn) + // !!! // ... + else if (handler isDefinedAt exception) + handler(exception) + else + throw exception + + def Finally(handler: Unit): a = + if (exception eq null) + result.asInstanceOf[a] + else + throw exception + } + + def caseFields(x: Product): List[Any] = { + val arity = x.productArity + def fields(from: Int): List[Any] = + if (from == arity) List() + else x.productElement(from) :: fields(from + 1) + fields(0) + } + + def _toString(x: Product): String = + caseFields(x).mkString(x.productPrefix + "(", ",", ")") + + def _hashCode(x: Product): Int = { + var code = x.getClass().hashCode() + val arr = x.productArity + var i = 0 + while (i < arr) { + val elem = x.productElement(i) + code = code * 41 + (if (elem == null) 0 else elem.hashCode()) + i += 1 + } + code + } + + def _equals(x: Product, y: Any): Boolean = y match { + case y1: Product if x.productArity == y1.productArity => + val arity = x.productArity + var i = 0 + while (i < arity && x.productElement(i) == y1.productElement(i)) + i += 1 + i == arity + case _ => + false + } + + def _equalsWithVarArgs(x: Product, y: Any): Boolean = y match { + case y1: Product if x.productArity == y1.productArity => + val arity = x.productArity + var i = 0 + while (i < arity - 1 && x.productElement(i) == y1.productElement(i)) + i += 1 + i == arity - 1 && { + x.productElement(i) match { + case xs: Seq[_] => + y1.productElement(i) match { + case ys: Seq[_] => xs sameElements ys + } + } + } + case _ => + false + } + + //def checkDefined[T >: Null](x: T): T = + // if (x == null) throw new UndefinedException else x + + def Seq[a](xs: a*): Seq[a] = null // interpreted specially by new backend. + + def arrayValue[A](x: BoxedArray[A], elemClass: Class[_]): AnyRef = + if (x eq null) null else x.unbox(elemClass) + + def boxArray(value: AnyRef): BoxedArray[_] = value match { + case x: Array[Byte] => new BoxedByteArray(x) +/* + case x: Array[Short] => new BoxedShortArray(x) + case x: Array[Char] => new BoxedCharArray(x) + case x: Array[Int] => new BoxedIntArray(x) + case x: Array[Long] => new BoxedLongArray(x) + case x: Array[Float] => new BoxedFloatArray(x) + case x: Array[Double] => new BoxedDoubleArray(x) + case x: Array[Boolean] => new BoxedBooleanArray(x) + case x: Array[AnyRef] => new BoxedObjectArray(x) +*/ + case x: BoxedArray[_] => x + } + + /** Given any Scala value, convert it to a String. + * + * The primary motivation for this method is to provide a means for + * correctly obtaining a String representation of a value, while + * avoiding the pitfalls of naïvely calling toString on said value. + * In particular, it addresses the fact that (a) toString cannot be + * called on null and (b) depending on the apparent type of an + * array, toString may or may not print it in a human-readable form. + * + * @param arg the value to stringify + * @return a string representation of <code>arg</code> + * + */ + def stringOf(arg : Any): String = arg match { + case null => "null" + case (arg : AnyRef) if isArray(arg) => boxArray(arg).deepToString + case arg => arg.toString + } +} diff --git a/src/library/scalax/runtime/StringVector.scala b/src/library/scalax/runtime/StringVector.scala index ee7a805449..c12243bed7 100644 --- a/src/library/scalax/runtime/StringVector.scala +++ b/src/library/scalax/runtime/StringVector.scala @@ -12,7 +12,7 @@ package scalax.runtime import collection.immutable.Vector -import collection.mutable.{ArrayBuffer, BuilderProxy} +import collection.mutable.ArrayBuffer import collection.generic.covariant.VectorTemplate object StringVector { @@ -22,7 +22,7 @@ object StringVector { } @cloneable -abstract class StringVector[+A] extends VectorTemplate[StringVector, A] with Vector[A] with Boxed[String] { +abstract class StringVector[+A] extends VectorTemplate[StringVector, A] with Vector[A] { /** The length of the string */ def length: Int @@ -31,12 +31,11 @@ abstract class StringVector[+A] extends VectorTemplate[StringVector, A] with Vec def apply(idx: Int): A /** Creates new builder for this collection */ - def newBuilder[B] = new BuilderProxy[StringVector, B] { - val self = new ArrayBuffer[B] - def result: StringVector[B] = new StringVector[B] { - def length = self.length - def apply(n: Int) = self.apply(n) - override def foreach(f: B => Unit) = self.foreach(f) + def newBuilder[B] = new ArrayBuffer[B].mapResult[StringVector] { // !!! Adriaan: can't drop [StringVector] here + buf => new StringVector[B] { + def length = buf.length + def apply(n: Int) = buf.apply(n) + override def foreach(f: B => Unit) = buf.foreach(f) } } diff --git a/src/library/scalax/util/control/Breaks.scala b/src/library/scalax/util/control/Breaks.scala index 6c938950d4..e89a03f76b 100755 --- a/src/library/scalax/util/control/Breaks.scala +++ b/src/library/scalax/util/control/Breaks.scala @@ -4,7 +4,7 @@ object Breaks { private class BreakException extends RuntimeException private val breakException = new BreakException private class ContinueException extends RuntimeException - private val continueException = new BreakException + private val continueException = new ContinueException /** A block from which one can exit with a `break' and which can be resumed with a `continue'. */ def breakable(op: => Unit) { |