diff options
Diffstat (limited to 'src/library')
696 files changed, 8678 insertions, 20979 deletions
diff --git a/src/library/rootdoc.txt b/src/library/rootdoc.txt index 0722d808bf..4795a47efe 100644 --- a/src/library/rootdoc.txt +++ b/src/library/rootdoc.txt @@ -2,21 +2,54 @@ This is the documentation for the Scala standard library. == Package structure == -The [[scala]] package contains core types. - -[[scala.collection `scala.collection`]] and its subpackages contain a collections framework with higher-order functions for manipulation. Both [[scala.collection.immutable `scala.collection.immutable`]] and [[scala.collection.mutable `scala.collection.mutable`]] data structures are available, with immutable as the default. The [[scala.collection.parallel `scala.collection.parallel`]] collections provide automatic parallel operation. - -Other important packages include: - - - [[scala.actors `scala.actors`]] - Concurrency framework inspired by Erlang. - - [[scala.io `scala.io`]] - Input and output. - - [[scala.math `scala.math`]] - Basic math functions and additional numeric types. - - [[scala.sys `scala.sys`]] - Interaction with other processes and the operating system. - - [[scala.util.matching `scala.util.matching`]] - Pattern matching in text using regular expressions. - - [[scala.util.parsing.combinator `scala.util.parsing.combinator`]] - Composable combinators for parsing. - - [[scala.xml `scala.xml`]] - XML parsing, manipulation, and serialization. - -Many other packages exist. See the complete list on the left. +The [[scala]] package contains core types like [[scala.Int `Int`]], [[scala.Float `Float`]], [[scala.Array `Array`]] +or [[scala.Option `Option`]] which are accessible in all Scala compilation units without explicit qualification or +imports. + +Notable packages include: + + - [[scala.collection `scala.collection`]] and its sub-packages contain Scala's collections framework + - [[scala.collection.immutable `scala.collection.immutable`]] - Immutable, sequential data-structures such as + [[scala.collection.immutable.Vector `Vector`]], [[scala.collection.immutable.List `List`]], + [[scala.collection.immutable.Range `Range`]], [[scala.collection.immutable.HashMap `HashMap`]] or + [[scala.collection.immutable.HashSet `HasSet`]] + - [[scala.collection.mutable `scala.collection.mutable`]] - Mutable, sequential data-structures such as + [[scala.collection.mutable.ArrayBuffer `ArrayBuffer`]], + [[scala.collection.mutable.StringBuilder `StringBuilder`]], + [[scala.collection.mutable.HashMap `HashMap`]] or [[scala.collection.mutable.HashSet `HashSet`]] + - [[scala.collection.concurrent `scala.collection.concurrent`]] - Mutable, concurrent data-structures such as + [[scala.collection.concurrent.TrieMap `TrieMap`]] + - [[scala.collection.parallel.immutable `scala.collection.parallel.immutable`]] - Immutable, parallel + data-structures such as [[scala.collection.parallel.immutable.ParVector `ParVector`]], + [[scala.collection.parallel.immutable.ParRange `ParRange`]], + [[scala.collection.parallel.immutable.ParHashMap `ParHashMap`]] or + [[scala.collection.parallel.immutable.ParHashSet `ParHashSet`]] + - [[scala.collection.parallel.mutable `scala.collection.parallel.mutable`]] - Mutable, parallel + data-structures such as [[scala.collection.parallel.mutable.ParArray `ParArray`]], + [[scala.collection.parallel.mutable.ParHashMap `ParHashMap`]], + [[scala.collection.parallel.mutable.ParTrieMap `ParTrieMap`]] or + [[scala.collection.parallel.mutable.ParHashSet `ParHashSet`]] + - [[scala.concurrent `scala.concurrent`]] - Primitives for concurrent programming such as + [[scala.concurrent.Future `Futures`]] and [[scala.concurrent.Promise `Promises`]] + - [[scala.io `scala.io`]] - Input and output operations + - [[scala.math `scala.math`]] - Basic math functions and additional numeric types like + [[scala.math.BigInt `BigInt`]] and [[scala.math.BigDecimal `BigDecimal`]] + - [[scala.sys `scala.sys`]] - Interaction with other processes and the operating system + - [[scala.util.matching `scala.util.matching`]] - [[scala.util.matching.Regex Regular expressions]] + +Other packages exist. See the complete list on the left. + +Additional parts of the standard library are shipped as separate libraries. These include: + + - [[scala.reflect `scala.reflect`]] - Scala's reflection API (scala-reflect.jar) + - [[scala.xml `scala.xml`]] - XML parsing, manipulation, and serialization (scala-xml.jar) + - [[scala.swing `scala.swing`]] - A convenient wrapper around Java's GUI framework called Swing (scala-swing.jar) + - [[scala.util.continuations `scala.util.continuations`]] - Delimited continuations using continuation-passing-style + (scala-continuations-library.jar, scala-continuations-plugin.jar) + - [[scala.util.parsing `scala.util.parsing`]] - [[scala.util.parsing.combinator Parser combinators]], including an + example implementation of a [[scala.util.parsing.json JSON parser]] (scala-parser-combinators.jar) + - [[scala.actors `scala.actors`]] - Actor-based concurrency (deprecated and replaced by Akka actors, + scala-actors.jar) == Automatic imports == diff --git a/src/library/scala/AnyVal.scala b/src/library/scala/AnyVal.scala index 0d6ba2454c..ff62948413 100644 --- a/src/library/scala/AnyVal.scala +++ b/src/library/scala/AnyVal.scala @@ -33,7 +33,7 @@ package scala * * User-defined value classes which avoid object allocation... * - * - must have a single, public `val` parameter that is the underlying runtime representation. + * - must have a single `val` parameter that is the underlying runtime representation. * - can define `def`s, but no `val`s, `var`s, or nested `traits`s, `class`es or `object`s. * - typically extend no other trait apart from `AnyVal`. * - cannot be used in type tests or pattern matching. @@ -52,6 +52,6 @@ package scala * as well as in [[http://docs.scala-lang.org/sips/pending/value-classes.html SIP-15: Value Classes]], * the Scala Improvement Proposal. */ -abstract class AnyVal extends Any with NotNull { +abstract class AnyVal extends Any { def getClass(): Class[_ <: AnyVal] = null } diff --git a/src/library/scala/App.scala b/src/library/scala/App.scala index 90a8977e81..62245322da 100644 --- a/src/library/scala/App.scala +++ b/src/library/scala/App.scala @@ -28,9 +28,10 @@ import scala.collection.mutable.ListBuffer * functionality, which means that fields of the object will not have been initialized * before the main method has been executed.''''' * - * It should also be noted that the `main` method will not normally need to be overridden: - * the purpose is to turn the whole class body into the “main method”. You should only - * chose to override it if you know what you are doing. + * It should also be noted that the `main` method should not be overridden: + * the whole class body becomes the “main method”. + * + * Future versions of this trait will no longer extend `DelayedInit`. * * @author Martin Odersky * @version 2.1, 15/02/2011 @@ -39,10 +40,12 @@ trait App extends DelayedInit { /** The time when the execution of this program started, in milliseconds since 1 * January 1970 UTC. */ + @deprecatedOverriding("executionStart should not be overridden", "2.11.0") val executionStart: Long = currentTime /** The command line arguments passed to the application's `main` method. */ + @deprecatedOverriding("args should not be overridden", "2.11.0") protected def args: Array[String] = _args private var _args: Array[String] = _ @@ -56,16 +59,18 @@ trait App extends DelayedInit { * themselves define a `delayedInit` method. * @param body the initialization code to be stored for later execution */ + @deprecated("The delayedInit mechanism will disappear.", "2.11.0") override def delayedInit(body: => Unit) { initCode += (() => body) } /** The main method. - * This stores all argument so that they can be retrieved with `args` - * and the executes all initialization code segments in the order they were - * passed to `delayedInit` + * This stores all arguments so that they can be retrieved with `args` + * and then executes all initialization code segments in the order in which + * they were passed to `delayedInit`. * @param args the arguments passed to the main method */ + @deprecatedOverriding("main should not be overridden", "2.11.0") def main(args: Array[String]) = { this._args = args for (proc <- initCode) proc() diff --git a/src/library/scala/Application.scala b/src/library/scala/Application.scala deleted file mode 100644 index e7db0d2db8..0000000000 --- a/src/library/scala/Application.scala +++ /dev/null @@ -1,79 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala - -import scala.compat.Platform.currentTime - -/** The `Application` trait can be used to quickly turn objects - * into executable programs, but is ''not recommended''. - * Here is an example: - * {{{ - * object Main extends Application { - * Console.println("Hello World!") - * } - * }}} - * Here, object `Main` inherits the `main` method of `Application`. - * The body of the `Main` object defines the main program. This technique - * does not work if the main program depends on command-line arguments - * (which are not accessible with the technique presented here). - * - * It is possible to time the execution of objects that inherit from class - * `Application` by setting the global `scala.time` - * property. Here is an example for benchmarking object `Main`: - * {{{ - * java -Dscala.time Main - * }}} - * In practice the `Application` trait has a number of serious pitfalls: - * - * - Threaded code that references the object will block until static - * initialization is complete. However, because the entire execution - * of an `object` extending `Application` takes place during - * static initialization, concurrent code will ''always'' deadlock if - * it must synchronize with the enclosing object. - * - As described above, there is no way to obtain the - * command-line arguments because all code in body of an `object` - * extending `Application` is run as part of the static initialization - * which occurs before `Application`'s `main` method - * even begins execution. - * - Static initializers are run only once during program execution, and - * JVM authors usually assume their execution to be relatively short. - * Therefore, certain JVM configurations may become confused, or simply - * fail to optimize or JIT the code in the body of an `object` extending - * `Application`. This can lead to a significant performance degradation. - * - * It is recommended to use the [[scala.App]] trait instead. - * {{{ - * object Main { - * def main(args: Array[String]) { - * //.. - * } - * } - * }}} - * - * @author Matthias Zenger - * @version 1.0, 10/09/2003 - */ -@deprecated("use App instead", "2.9.0") -trait Application { - - /** The time when the execution of this program started, - * in milliseconds since 1 January 1970 UTC. */ - val executionStart: Long = currentTime - - /** The default main method. - * - * @param args the arguments passed to the main method - */ - def main(args: Array[String]) { - if (util.Properties propIsSet "scala.time") { - val total = currentTime - executionStart - Console.println("[total " + total + "ms]") - } - } -} diff --git a/src/library/scala/Array.scala b/src/library/scala/Array.scala index b9f51803ec..6ab82d998e 100644 --- a/src/library/scala/Array.scala +++ b/src/library/scala/Array.scala @@ -240,9 +240,9 @@ object Array extends FallbackArrayBuilding { */ def concat[T: ClassTag](xss: Array[T]*): Array[T] = { val b = newBuilder[T] - b.sizeHint(xss.map(_.size).sum) + b.sizeHint(xss.map(_.length).sum) for (xs <- xss) b ++= xs - b.result + b.result() } /** Returns an array that contains the results of some element computation a number @@ -267,7 +267,7 @@ object Array extends FallbackArrayBuilding { b += elem i += 1 } - b.result + b.result() } /** Returns a two-dimensional array that contains the results of some element @@ -331,7 +331,7 @@ object Array extends FallbackArrayBuilding { b += f(i) i += 1 } - b.result + b.result() } /** Returns a two-dimensional array containing values of a given function @@ -399,14 +399,14 @@ object Array extends FallbackArrayBuilding { def range(start: Int, end: Int, step: Int): Array[Int] = { if (step == 0) throw new IllegalArgumentException("zero step") val b = newBuilder[Int] - b.sizeHint(immutable.Range.count(start, end, step, false)) + b.sizeHint(immutable.Range.count(start, end, step, isInclusive = false)) var i = start while (if (step < 0) end < i else i < end) { b += i i += step } - b.result + b.result() } /** Returns an array containing repeated applications of a function to a start value. @@ -431,7 +431,7 @@ object Array extends FallbackArrayBuilding { b += acc } } - b.result + b.result() } /** Called in a pattern match like `{ case Array(x,y,z) => println('3 elements')}`. diff --git a/src/library/scala/Boolean.scala b/src/library/scala/Boolean.scala index 440e546f19..53b4fb2af2 100644 --- a/src/library/scala/Boolean.scala +++ b/src/library/scala/Boolean.scala @@ -1,17 +1,17 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** +** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** \* */ -// DO NOT EDIT, CHANGES WILL BE LOST. +// DO NOT EDIT, CHANGES WILL BE LOST +// This auto-generated code can be modified in scala.tools.cmd.gen. +// Afterwards, running tools/codegen-anyvals regenerates this source file. package scala -import scala.language.implicitConversions - /** `Boolean` (equivalent to Java's `boolean` primitive type) is a * subtype of [[scala.AnyVal]]. Instances of `Boolean` are not * represented by an object in the underlying runtime system. @@ -20,18 +20,16 @@ import scala.language.implicitConversions * which provides useful non-primitive operations. */ final abstract class Boolean private extends AnyVal { - /** - * Negates a Boolean expression. - * - * - `!a` results in `false` if and only if `a` evaluates to `true` and - * - `!a` results in `true` if and only if `a` evaluates to `false`. - * - * @return the negated expression - */ + /** Negates a Boolean expression. + * + * - `!a` results in `false` if and only if `a` evaluates to `true` and + * - `!a` results in `true` if and only if `a` evaluates to `false`. + * + * @return the negated expression + */ def unary_! : Boolean - /** - * Compares two Boolean expressions and returns `true` if they evaluate to the same value. + /** Compares two Boolean expressions and returns `true` if they evaluate to the same value. * * `a == b` returns `true` if and only if * - `a` and `b` are `true` or @@ -48,8 +46,7 @@ final abstract class Boolean private extends AnyVal { */ def !=(x: Boolean): Boolean - /** - * Compares two Boolean expressions and returns `true` if one or both of them evaluate to true. + /** Compares two Boolean expressions and returns `true` if one or both of them evaluate to true. * * `a || b` returns `true` if and only if * - `a` is `true` or @@ -62,8 +59,7 @@ final abstract class Boolean private extends AnyVal { */ def ||(x: Boolean): Boolean - /** - * Compares two Boolean expressions and returns `true` if both of them evaluate to true. + /** Compares two Boolean expressions and returns `true` if both of them evaluate to true. * * `a && b` returns `true` if and only if * - `a` and `b` are `true`. @@ -78,8 +74,7 @@ final abstract class Boolean private extends AnyVal { // def ||(x: => Boolean): Boolean // def &&(x: => Boolean): Boolean - /** - * Compares two Boolean expressions and returns `true` if one or both of them evaluate to true. + /** Compares two Boolean expressions and returns `true` if one or both of them evaluate to true. * * `a | b` returns `true` if and only if * - `a` is `true` or @@ -90,8 +85,7 @@ final abstract class Boolean private extends AnyVal { */ def |(x: Boolean): Boolean - /** - * Compares two Boolean expressions and returns `true` if both of them evaluate to true. + /** Compares two Boolean expressions and returns `true` if both of them evaluate to true. * * `a & b` returns `true` if and only if * - `a` and `b` are `true`. @@ -100,8 +94,7 @@ final abstract class Boolean private extends AnyVal { */ def &(x: Boolean): Boolean - /** - * Compares two Boolean expressions and returns `true` if they evaluate to a different value. + /** Compares two Boolean expressions and returns `true` if they evaluate to a different value. * * `a ^ b` returns `true` if and only if * - `a` is `true` and `b` is `false` or @@ -116,6 +109,8 @@ object Boolean extends AnyValCompanion { /** Transform a value type into a boxed reference type. * + * Runtime implementation determined by `scala.runtime.BoxesRunTime.boxToBoolean`. See [[https://github.com/scala/scala src/library/scala/runtime/BoxesRunTime.java]]. + * * @param x the Boolean to be boxed * @return a java.lang.Boolean offering `x` as its underlying value. */ @@ -125,14 +120,15 @@ object Boolean extends AnyValCompanion { * method is not typesafe: it accepts any Object, but will throw * an exception if the argument is not a java.lang.Boolean. * + * Runtime implementation determined by `scala.runtime.BoxesRunTime.unboxToBoolean`. See [[https://github.com/scala/scala src/library/scala/runtime/BoxesRunTime.java]]. + * * @param x the java.lang.Boolean to be unboxed. * @throws ClassCastException if the argument is not a java.lang.Boolean * @return the Boolean resulting from calling booleanValue() on `x` */ def unbox(x: java.lang.Object): Boolean = x.asInstanceOf[java.lang.Boolean].booleanValue() - /** The String representation of the scala.Boolean companion object. - */ + /** The String representation of the scala.Boolean companion object. */ override def toString = "object scala.Boolean" } diff --git a/src/library/scala/Byte.scala b/src/library/scala/Byte.scala index df0d2c73b1..413231c0d1 100644 --- a/src/library/scala/Byte.scala +++ b/src/library/scala/Byte.scala @@ -1,17 +1,17 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** +** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** \* */ -// DO NOT EDIT, CHANGES WILL BE LOST. +// DO NOT EDIT, CHANGES WILL BE LOST +// This auto-generated code can be modified in scala.tools.cmd.gen. +// Afterwards, running tools/codegen-anyvals regenerates this source file. package scala -import scala.language.implicitConversions - /** `Byte`, a 8-bit signed integer (equivalent to Java's `byte` primitive type) is a * subtype of [[scala.AnyVal]]. Instances of `Byte` are not * represented by an object in the underlying runtime system. @@ -37,13 +37,9 @@ final abstract class Byte private extends AnyVal { * }}} */ def unary_~ : Int - /** - * Returns this value, unmodified. - */ + /** Returns this value, unmodified. */ def unary_+ : Int - /** - * Returns the negation of this value. - */ + /** Returns the negation of this value. */ def unary_- : Int def +(x: String): String @@ -105,178 +101,94 @@ final abstract class Byte private extends AnyVal { */ def >>(x: Long): Int - /** - * Returns `true` if this value is equal to x, `false` otherwise. - */ + /** Returns `true` if this value is equal to x, `false` otherwise. */ def ==(x: Byte): Boolean - /** - * Returns `true` if this value is equal to x, `false` otherwise. - */ + /** Returns `true` if this value is equal to x, `false` otherwise. */ def ==(x: Short): Boolean - /** - * Returns `true` if this value is equal to x, `false` otherwise. - */ + /** Returns `true` if this value is equal to x, `false` otherwise. */ def ==(x: Char): Boolean - /** - * Returns `true` if this value is equal to x, `false` otherwise. - */ + /** Returns `true` if this value is equal to x, `false` otherwise. */ def ==(x: Int): Boolean - /** - * Returns `true` if this value is equal to x, `false` otherwise. - */ + /** Returns `true` if this value is equal to x, `false` otherwise. */ def ==(x: Long): Boolean - /** - * Returns `true` if this value is equal to x, `false` otherwise. - */ + /** Returns `true` if this value is equal to x, `false` otherwise. */ def ==(x: Float): Boolean - /** - * Returns `true` if this value is equal to x, `false` otherwise. - */ + /** Returns `true` if this value is equal to x, `false` otherwise. */ def ==(x: Double): Boolean - /** - * Returns `true` if this value is not equal to x, `false` otherwise. - */ + /** Returns `true` if this value is not equal to x, `false` otherwise. */ def !=(x: Byte): Boolean - /** - * Returns `true` if this value is not equal to x, `false` otherwise. - */ + /** Returns `true` if this value is not equal to x, `false` otherwise. */ def !=(x: Short): Boolean - /** - * Returns `true` if this value is not equal to x, `false` otherwise. - */ + /** Returns `true` if this value is not equal to x, `false` otherwise. */ def !=(x: Char): Boolean - /** - * Returns `true` if this value is not equal to x, `false` otherwise. - */ + /** Returns `true` if this value is not equal to x, `false` otherwise. */ def !=(x: Int): Boolean - /** - * Returns `true` if this value is not equal to x, `false` otherwise. - */ + /** Returns `true` if this value is not equal to x, `false` otherwise. */ def !=(x: Long): Boolean - /** - * Returns `true` if this value is not equal to x, `false` otherwise. - */ + /** Returns `true` if this value is not equal to x, `false` otherwise. */ def !=(x: Float): Boolean - /** - * Returns `true` if this value is not equal to x, `false` otherwise. - */ + /** Returns `true` if this value is not equal to x, `false` otherwise. */ def !=(x: Double): Boolean - /** - * Returns `true` if this value is less than x, `false` otherwise. - */ + /** Returns `true` if this value is less than x, `false` otherwise. */ def <(x: Byte): Boolean - /** - * Returns `true` if this value is less than x, `false` otherwise. - */ + /** Returns `true` if this value is less than x, `false` otherwise. */ def <(x: Short): Boolean - /** - * Returns `true` if this value is less than x, `false` otherwise. - */ + /** Returns `true` if this value is less than x, `false` otherwise. */ def <(x: Char): Boolean - /** - * Returns `true` if this value is less than x, `false` otherwise. - */ + /** Returns `true` if this value is less than x, `false` otherwise. */ def <(x: Int): Boolean - /** - * Returns `true` if this value is less than x, `false` otherwise. - */ + /** Returns `true` if this value is less than x, `false` otherwise. */ def <(x: Long): Boolean - /** - * Returns `true` if this value is less than x, `false` otherwise. - */ + /** Returns `true` if this value is less than x, `false` otherwise. */ def <(x: Float): Boolean - /** - * Returns `true` if this value is less than x, `false` otherwise. - */ + /** Returns `true` if this value is less than x, `false` otherwise. */ def <(x: Double): Boolean - /** - * Returns `true` if this value is less than or equal to x, `false` otherwise. - */ + /** Returns `true` if this value is less than or equal to x, `false` otherwise. */ def <=(x: Byte): Boolean - /** - * Returns `true` if this value is less than or equal to x, `false` otherwise. - */ + /** Returns `true` if this value is less than or equal to x, `false` otherwise. */ def <=(x: Short): Boolean - /** - * Returns `true` if this value is less than or equal to x, `false` otherwise. - */ + /** Returns `true` if this value is less than or equal to x, `false` otherwise. */ def <=(x: Char): Boolean - /** - * Returns `true` if this value is less than or equal to x, `false` otherwise. - */ + /** Returns `true` if this value is less than or equal to x, `false` otherwise. */ def <=(x: Int): Boolean - /** - * Returns `true` if this value is less than or equal to x, `false` otherwise. - */ + /** Returns `true` if this value is less than or equal to x, `false` otherwise. */ def <=(x: Long): Boolean - /** - * Returns `true` if this value is less than or equal to x, `false` otherwise. - */ + /** Returns `true` if this value is less than or equal to x, `false` otherwise. */ def <=(x: Float): Boolean - /** - * Returns `true` if this value is less than or equal to x, `false` otherwise. - */ + /** Returns `true` if this value is less than or equal to x, `false` otherwise. */ def <=(x: Double): Boolean - /** - * Returns `true` if this value is greater than x, `false` otherwise. - */ + /** Returns `true` if this value is greater than x, `false` otherwise. */ def >(x: Byte): Boolean - /** - * Returns `true` if this value is greater than x, `false` otherwise. - */ + /** Returns `true` if this value is greater than x, `false` otherwise. */ def >(x: Short): Boolean - /** - * Returns `true` if this value is greater than x, `false` otherwise. - */ + /** Returns `true` if this value is greater than x, `false` otherwise. */ def >(x: Char): Boolean - /** - * Returns `true` if this value is greater than x, `false` otherwise. - */ + /** Returns `true` if this value is greater than x, `false` otherwise. */ def >(x: Int): Boolean - /** - * Returns `true` if this value is greater than x, `false` otherwise. - */ + /** Returns `true` if this value is greater than x, `false` otherwise. */ def >(x: Long): Boolean - /** - * Returns `true` if this value is greater than x, `false` otherwise. - */ + /** Returns `true` if this value is greater than x, `false` otherwise. */ def >(x: Float): Boolean - /** - * Returns `true` if this value is greater than x, `false` otherwise. - */ + /** Returns `true` if this value is greater than x, `false` otherwise. */ def >(x: Double): Boolean - /** - * Returns `true` if this value is greater than or equal to x, `false` otherwise. - */ + /** Returns `true` if this value is greater than or equal to x, `false` otherwise. */ def >=(x: Byte): Boolean - /** - * Returns `true` if this value is greater than or equal to x, `false` otherwise. - */ + /** Returns `true` if this value is greater than or equal to x, `false` otherwise. */ def >=(x: Short): Boolean - /** - * Returns `true` if this value is greater than or equal to x, `false` otherwise. - */ + /** Returns `true` if this value is greater than or equal to x, `false` otherwise. */ def >=(x: Char): Boolean - /** - * Returns `true` if this value is greater than or equal to x, `false` otherwise. - */ + /** Returns `true` if this value is greater than or equal to x, `false` otherwise. */ def >=(x: Int): Boolean - /** - * Returns `true` if this value is greater than or equal to x, `false` otherwise. - */ + /** Returns `true` if this value is greater than or equal to x, `false` otherwise. */ def >=(x: Long): Boolean - /** - * Returns `true` if this value is greater than or equal to x, `false` otherwise. - */ + /** Returns `true` if this value is greater than or equal to x, `false` otherwise. */ def >=(x: Float): Boolean - /** - * Returns `true` if this value is greater than or equal to x, `false` otherwise. - */ + /** Returns `true` if this value is greater than or equal to x, `false` otherwise. */ def >=(x: Double): Boolean /** @@ -447,165 +359,95 @@ final abstract class Byte private extends AnyVal { */ def ^(x: Long): Long - /** - * Returns the sum of this value and `x`. - */ + /** Returns the sum of this value and `x`. */ def +(x: Byte): Int - /** - * Returns the sum of this value and `x`. - */ + /** Returns the sum of this value and `x`. */ def +(x: Short): Int - /** - * Returns the sum of this value and `x`. - */ + /** Returns the sum of this value and `x`. */ def +(x: Char): Int - /** - * Returns the sum of this value and `x`. - */ + /** Returns the sum of this value and `x`. */ def +(x: Int): Int - /** - * Returns the sum of this value and `x`. - */ + /** Returns the sum of this value and `x`. */ def +(x: Long): Long - /** - * Returns the sum of this value and `x`. - */ + /** Returns the sum of this value and `x`. */ def +(x: Float): Float - /** - * Returns the sum of this value and `x`. - */ + /** Returns the sum of this value and `x`. */ def +(x: Double): Double - /** - * Returns the difference of this value and `x`. - */ + /** Returns the difference of this value and `x`. */ def -(x: Byte): Int - /** - * Returns the difference of this value and `x`. - */ + /** Returns the difference of this value and `x`. */ def -(x: Short): Int - /** - * Returns the difference of this value and `x`. - */ + /** Returns the difference of this value and `x`. */ def -(x: Char): Int - /** - * Returns the difference of this value and `x`. - */ + /** Returns the difference of this value and `x`. */ def -(x: Int): Int - /** - * Returns the difference of this value and `x`. - */ + /** Returns the difference of this value and `x`. */ def -(x: Long): Long - /** - * Returns the difference of this value and `x`. - */ + /** Returns the difference of this value and `x`. */ def -(x: Float): Float - /** - * Returns the difference of this value and `x`. - */ + /** Returns the difference of this value and `x`. */ def -(x: Double): Double - /** - * Returns the product of this value and `x`. - */ + /** Returns the product of this value and `x`. */ def *(x: Byte): Int - /** - * Returns the product of this value and `x`. - */ + /** Returns the product of this value and `x`. */ def *(x: Short): Int - /** - * Returns the product of this value and `x`. - */ + /** Returns the product of this value and `x`. */ def *(x: Char): Int - /** - * Returns the product of this value and `x`. - */ + /** Returns the product of this value and `x`. */ def *(x: Int): Int - /** - * Returns the product of this value and `x`. - */ + /** Returns the product of this value and `x`. */ def *(x: Long): Long - /** - * Returns the product of this value and `x`. - */ + /** Returns the product of this value and `x`. */ def *(x: Float): Float - /** - * Returns the product of this value and `x`. - */ + /** Returns the product of this value and `x`. */ def *(x: Double): Double - /** - * Returns the quotient of this value and `x`. - */ + /** Returns the quotient of this value and `x`. */ def /(x: Byte): Int - /** - * Returns the quotient of this value and `x`. - */ + /** Returns the quotient of this value and `x`. */ def /(x: Short): Int - /** - * Returns the quotient of this value and `x`. - */ + /** Returns the quotient of this value and `x`. */ def /(x: Char): Int - /** - * Returns the quotient of this value and `x`. - */ + /** Returns the quotient of this value and `x`. */ def /(x: Int): Int - /** - * Returns the quotient of this value and `x`. - */ + /** Returns the quotient of this value and `x`. */ def /(x: Long): Long - /** - * Returns the quotient of this value and `x`. - */ + /** Returns the quotient of this value and `x`. */ def /(x: Float): Float - /** - * Returns the quotient of this value and `x`. - */ + /** Returns the quotient of this value and `x`. */ def /(x: Double): Double - /** - * Returns the remainder of the division of this value by `x`. - */ + /** Returns the remainder of the division of this value by `x`. */ def %(x: Byte): Int - /** - * Returns the remainder of the division of this value by `x`. - */ + /** Returns the remainder of the division of this value by `x`. */ def %(x: Short): Int - /** - * Returns the remainder of the division of this value by `x`. - */ + /** Returns the remainder of the division of this value by `x`. */ def %(x: Char): Int - /** - * Returns the remainder of the division of this value by `x`. - */ + /** Returns the remainder of the division of this value by `x`. */ def %(x: Int): Int - /** - * Returns the remainder of the division of this value by `x`. - */ + /** Returns the remainder of the division of this value by `x`. */ def %(x: Long): Long - /** - * Returns the remainder of the division of this value by `x`. - */ + /** Returns the remainder of the division of this value by `x`. */ def %(x: Float): Float - /** - * Returns the remainder of the division of this value by `x`. - */ + /** Returns the remainder of the division of this value by `x`. */ def %(x: Double): Double override def getClass(): Class[Byte] = null } object Byte extends AnyValCompanion { - /** The smallest value representable as a Byte. - */ + /** The smallest value representable as a Byte. */ final val MinValue = java.lang.Byte.MIN_VALUE - /** The largest value representable as a Byte. - */ + /** The largest value representable as a Byte. */ final val MaxValue = java.lang.Byte.MAX_VALUE /** Transform a value type into a boxed reference type. * + * Runtime implementation determined by `scala.runtime.BoxesRunTime.boxToByte`. See [[https://github.com/scala/scala src/library/scala/runtime/BoxesRunTime.java]]. + * * @param x the Byte to be boxed * @return a java.lang.Byte offering `x` as its underlying value. */ @@ -615,18 +457,18 @@ object Byte extends AnyValCompanion { * method is not typesafe: it accepts any Object, but will throw * an exception if the argument is not a java.lang.Byte. * + * Runtime implementation determined by `scala.runtime.BoxesRunTime.unboxToByte`. See [[https://github.com/scala/scala src/library/scala/runtime/BoxesRunTime.java]]. + * * @param x the java.lang.Byte to be unboxed. * @throws ClassCastException if the argument is not a java.lang.Byte * @return the Byte resulting from calling byteValue() on `x` */ def unbox(x: java.lang.Object): Byte = x.asInstanceOf[java.lang.Byte].byteValue() - /** The String representation of the scala.Byte companion object. - */ + /** The String representation of the scala.Byte companion object. */ override def toString = "object scala.Byte" - - /** Language mandated coercions from Byte to "wider" types. - */ + /** Language mandated coercions from Byte to "wider" types. */ + import scala.language.implicitConversions implicit def byte2short(x: Byte): Short = x.toShort implicit def byte2int(x: Byte): Int = x.toInt implicit def byte2long(x: Byte): Long = x.toLong diff --git a/src/library/scala/Char.scala b/src/library/scala/Char.scala index 1fa0c0d9e8..ec2d48c181 100644 --- a/src/library/scala/Char.scala +++ b/src/library/scala/Char.scala @@ -1,17 +1,17 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** +** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** \* */ -// DO NOT EDIT, CHANGES WILL BE LOST. +// DO NOT EDIT, CHANGES WILL BE LOST +// This auto-generated code can be modified in scala.tools.cmd.gen. +// Afterwards, running tools/codegen-anyvals regenerates this source file. package scala -import scala.language.implicitConversions - /** `Char`, a 16-bit unsigned integer (equivalent to Java's `char` primitive type) is a * subtype of [[scala.AnyVal]]. Instances of `Char` are not * represented by an object in the underlying runtime system. @@ -37,13 +37,9 @@ final abstract class Char private extends AnyVal { * }}} */ def unary_~ : Int - /** - * Returns this value, unmodified. - */ + /** Returns this value, unmodified. */ def unary_+ : Int - /** - * Returns the negation of this value. - */ + /** Returns the negation of this value. */ def unary_- : Int def +(x: String): String @@ -105,178 +101,94 @@ final abstract class Char private extends AnyVal { */ def >>(x: Long): Int - /** - * Returns `true` if this value is equal to x, `false` otherwise. - */ + /** Returns `true` if this value is equal to x, `false` otherwise. */ def ==(x: Byte): Boolean - /** - * Returns `true` if this value is equal to x, `false` otherwise. - */ + /** Returns `true` if this value is equal to x, `false` otherwise. */ def ==(x: Short): Boolean - /** - * Returns `true` if this value is equal to x, `false` otherwise. - */ + /** Returns `true` if this value is equal to x, `false` otherwise. */ def ==(x: Char): Boolean - /** - * Returns `true` if this value is equal to x, `false` otherwise. - */ + /** Returns `true` if this value is equal to x, `false` otherwise. */ def ==(x: Int): Boolean - /** - * Returns `true` if this value is equal to x, `false` otherwise. - */ + /** Returns `true` if this value is equal to x, `false` otherwise. */ def ==(x: Long): Boolean - /** - * Returns `true` if this value is equal to x, `false` otherwise. - */ + /** Returns `true` if this value is equal to x, `false` otherwise. */ def ==(x: Float): Boolean - /** - * Returns `true` if this value is equal to x, `false` otherwise. - */ + /** Returns `true` if this value is equal to x, `false` otherwise. */ def ==(x: Double): Boolean - /** - * Returns `true` if this value is not equal to x, `false` otherwise. - */ + /** Returns `true` if this value is not equal to x, `false` otherwise. */ def !=(x: Byte): Boolean - /** - * Returns `true` if this value is not equal to x, `false` otherwise. - */ + /** Returns `true` if this value is not equal to x, `false` otherwise. */ def !=(x: Short): Boolean - /** - * Returns `true` if this value is not equal to x, `false` otherwise. - */ + /** Returns `true` if this value is not equal to x, `false` otherwise. */ def !=(x: Char): Boolean - /** - * Returns `true` if this value is not equal to x, `false` otherwise. - */ + /** Returns `true` if this value is not equal to x, `false` otherwise. */ def !=(x: Int): Boolean - /** - * Returns `true` if this value is not equal to x, `false` otherwise. - */ + /** Returns `true` if this value is not equal to x, `false` otherwise. */ def !=(x: Long): Boolean - /** - * Returns `true` if this value is not equal to x, `false` otherwise. - */ + /** Returns `true` if this value is not equal to x, `false` otherwise. */ def !=(x: Float): Boolean - /** - * Returns `true` if this value is not equal to x, `false` otherwise. - */ + /** Returns `true` if this value is not equal to x, `false` otherwise. */ def !=(x: Double): Boolean - /** - * Returns `true` if this value is less than x, `false` otherwise. - */ + /** Returns `true` if this value is less than x, `false` otherwise. */ def <(x: Byte): Boolean - /** - * Returns `true` if this value is less than x, `false` otherwise. - */ + /** Returns `true` if this value is less than x, `false` otherwise. */ def <(x: Short): Boolean - /** - * Returns `true` if this value is less than x, `false` otherwise. - */ + /** Returns `true` if this value is less than x, `false` otherwise. */ def <(x: Char): Boolean - /** - * Returns `true` if this value is less than x, `false` otherwise. - */ + /** Returns `true` if this value is less than x, `false` otherwise. */ def <(x: Int): Boolean - /** - * Returns `true` if this value is less than x, `false` otherwise. - */ + /** Returns `true` if this value is less than x, `false` otherwise. */ def <(x: Long): Boolean - /** - * Returns `true` if this value is less than x, `false` otherwise. - */ + /** Returns `true` if this value is less than x, `false` otherwise. */ def <(x: Float): Boolean - /** - * Returns `true` if this value is less than x, `false` otherwise. - */ + /** Returns `true` if this value is less than x, `false` otherwise. */ def <(x: Double): Boolean - /** - * Returns `true` if this value is less than or equal to x, `false` otherwise. - */ + /** Returns `true` if this value is less than or equal to x, `false` otherwise. */ def <=(x: Byte): Boolean - /** - * Returns `true` if this value is less than or equal to x, `false` otherwise. - */ + /** Returns `true` if this value is less than or equal to x, `false` otherwise. */ def <=(x: Short): Boolean - /** - * Returns `true` if this value is less than or equal to x, `false` otherwise. - */ + /** Returns `true` if this value is less than or equal to x, `false` otherwise. */ def <=(x: Char): Boolean - /** - * Returns `true` if this value is less than or equal to x, `false` otherwise. - */ + /** Returns `true` if this value is less than or equal to x, `false` otherwise. */ def <=(x: Int): Boolean - /** - * Returns `true` if this value is less than or equal to x, `false` otherwise. - */ + /** Returns `true` if this value is less than or equal to x, `false` otherwise. */ def <=(x: Long): Boolean - /** - * Returns `true` if this value is less than or equal to x, `false` otherwise. - */ + /** Returns `true` if this value is less than or equal to x, `false` otherwise. */ def <=(x: Float): Boolean - /** - * Returns `true` if this value is less than or equal to x, `false` otherwise. - */ + /** Returns `true` if this value is less than or equal to x, `false` otherwise. */ def <=(x: Double): Boolean - /** - * Returns `true` if this value is greater than x, `false` otherwise. - */ + /** Returns `true` if this value is greater than x, `false` otherwise. */ def >(x: Byte): Boolean - /** - * Returns `true` if this value is greater than x, `false` otherwise. - */ + /** Returns `true` if this value is greater than x, `false` otherwise. */ def >(x: Short): Boolean - /** - * Returns `true` if this value is greater than x, `false` otherwise. - */ + /** Returns `true` if this value is greater than x, `false` otherwise. */ def >(x: Char): Boolean - /** - * Returns `true` if this value is greater than x, `false` otherwise. - */ + /** Returns `true` if this value is greater than x, `false` otherwise. */ def >(x: Int): Boolean - /** - * Returns `true` if this value is greater than x, `false` otherwise. - */ + /** Returns `true` if this value is greater than x, `false` otherwise. */ def >(x: Long): Boolean - /** - * Returns `true` if this value is greater than x, `false` otherwise. - */ + /** Returns `true` if this value is greater than x, `false` otherwise. */ def >(x: Float): Boolean - /** - * Returns `true` if this value is greater than x, `false` otherwise. - */ + /** Returns `true` if this value is greater than x, `false` otherwise. */ def >(x: Double): Boolean - /** - * Returns `true` if this value is greater than or equal to x, `false` otherwise. - */ + /** Returns `true` if this value is greater than or equal to x, `false` otherwise. */ def >=(x: Byte): Boolean - /** - * Returns `true` if this value is greater than or equal to x, `false` otherwise. - */ + /** Returns `true` if this value is greater than or equal to x, `false` otherwise. */ def >=(x: Short): Boolean - /** - * Returns `true` if this value is greater than or equal to x, `false` otherwise. - */ + /** Returns `true` if this value is greater than or equal to x, `false` otherwise. */ def >=(x: Char): Boolean - /** - * Returns `true` if this value is greater than or equal to x, `false` otherwise. - */ + /** Returns `true` if this value is greater than or equal to x, `false` otherwise. */ def >=(x: Int): Boolean - /** - * Returns `true` if this value is greater than or equal to x, `false` otherwise. - */ + /** Returns `true` if this value is greater than or equal to x, `false` otherwise. */ def >=(x: Long): Boolean - /** - * Returns `true` if this value is greater than or equal to x, `false` otherwise. - */ + /** Returns `true` if this value is greater than or equal to x, `false` otherwise. */ def >=(x: Float): Boolean - /** - * Returns `true` if this value is greater than or equal to x, `false` otherwise. - */ + /** Returns `true` if this value is greater than or equal to x, `false` otherwise. */ def >=(x: Double): Boolean /** @@ -447,165 +359,95 @@ final abstract class Char private extends AnyVal { */ def ^(x: Long): Long - /** - * Returns the sum of this value and `x`. - */ + /** Returns the sum of this value and `x`. */ def +(x: Byte): Int - /** - * Returns the sum of this value and `x`. - */ + /** Returns the sum of this value and `x`. */ def +(x: Short): Int - /** - * Returns the sum of this value and `x`. - */ + /** Returns the sum of this value and `x`. */ def +(x: Char): Int - /** - * Returns the sum of this value and `x`. - */ + /** Returns the sum of this value and `x`. */ def +(x: Int): Int - /** - * Returns the sum of this value and `x`. - */ + /** Returns the sum of this value and `x`. */ def +(x: Long): Long - /** - * Returns the sum of this value and `x`. - */ + /** Returns the sum of this value and `x`. */ def +(x: Float): Float - /** - * Returns the sum of this value and `x`. - */ + /** Returns the sum of this value and `x`. */ def +(x: Double): Double - /** - * Returns the difference of this value and `x`. - */ + /** Returns the difference of this value and `x`. */ def -(x: Byte): Int - /** - * Returns the difference of this value and `x`. - */ + /** Returns the difference of this value and `x`. */ def -(x: Short): Int - /** - * Returns the difference of this value and `x`. - */ + /** Returns the difference of this value and `x`. */ def -(x: Char): Int - /** - * Returns the difference of this value and `x`. - */ + /** Returns the difference of this value and `x`. */ def -(x: Int): Int - /** - * Returns the difference of this value and `x`. - */ + /** Returns the difference of this value and `x`. */ def -(x: Long): Long - /** - * Returns the difference of this value and `x`. - */ + /** Returns the difference of this value and `x`. */ def -(x: Float): Float - /** - * Returns the difference of this value and `x`. - */ + /** Returns the difference of this value and `x`. */ def -(x: Double): Double - /** - * Returns the product of this value and `x`. - */ + /** Returns the product of this value and `x`. */ def *(x: Byte): Int - /** - * Returns the product of this value and `x`. - */ + /** Returns the product of this value and `x`. */ def *(x: Short): Int - /** - * Returns the product of this value and `x`. - */ + /** Returns the product of this value and `x`. */ def *(x: Char): Int - /** - * Returns the product of this value and `x`. - */ + /** Returns the product of this value and `x`. */ def *(x: Int): Int - /** - * Returns the product of this value and `x`. - */ + /** Returns the product of this value and `x`. */ def *(x: Long): Long - /** - * Returns the product of this value and `x`. - */ + /** Returns the product of this value and `x`. */ def *(x: Float): Float - /** - * Returns the product of this value and `x`. - */ + /** Returns the product of this value and `x`. */ def *(x: Double): Double - /** - * Returns the quotient of this value and `x`. - */ + /** Returns the quotient of this value and `x`. */ def /(x: Byte): Int - /** - * Returns the quotient of this value and `x`. - */ + /** Returns the quotient of this value and `x`. */ def /(x: Short): Int - /** - * Returns the quotient of this value and `x`. - */ + /** Returns the quotient of this value and `x`. */ def /(x: Char): Int - /** - * Returns the quotient of this value and `x`. - */ + /** Returns the quotient of this value and `x`. */ def /(x: Int): Int - /** - * Returns the quotient of this value and `x`. - */ + /** Returns the quotient of this value and `x`. */ def /(x: Long): Long - /** - * Returns the quotient of this value and `x`. - */ + /** Returns the quotient of this value and `x`. */ def /(x: Float): Float - /** - * Returns the quotient of this value and `x`. - */ + /** Returns the quotient of this value and `x`. */ def /(x: Double): Double - /** - * Returns the remainder of the division of this value by `x`. - */ + /** Returns the remainder of the division of this value by `x`. */ def %(x: Byte): Int - /** - * Returns the remainder of the division of this value by `x`. - */ + /** Returns the remainder of the division of this value by `x`. */ def %(x: Short): Int - /** - * Returns the remainder of the division of this value by `x`. - */ + /** Returns the remainder of the division of this value by `x`. */ def %(x: Char): Int - /** - * Returns the remainder of the division of this value by `x`. - */ + /** Returns the remainder of the division of this value by `x`. */ def %(x: Int): Int - /** - * Returns the remainder of the division of this value by `x`. - */ + /** Returns the remainder of the division of this value by `x`. */ def %(x: Long): Long - /** - * Returns the remainder of the division of this value by `x`. - */ + /** Returns the remainder of the division of this value by `x`. */ def %(x: Float): Float - /** - * Returns the remainder of the division of this value by `x`. - */ + /** Returns the remainder of the division of this value by `x`. */ def %(x: Double): Double override def getClass(): Class[Char] = null } object Char extends AnyValCompanion { - /** The smallest value representable as a Char. - */ + /** The smallest value representable as a Char. */ final val MinValue = java.lang.Character.MIN_VALUE - /** The largest value representable as a Char. - */ + /** The largest value representable as a Char. */ final val MaxValue = java.lang.Character.MAX_VALUE /** Transform a value type into a boxed reference type. * + * Runtime implementation determined by `scala.runtime.BoxesRunTime.boxToCharacter`. See [[https://github.com/scala/scala src/library/scala/runtime/BoxesRunTime.java]]. + * * @param x the Char to be boxed * @return a java.lang.Character offering `x` as its underlying value. */ @@ -615,18 +457,18 @@ object Char extends AnyValCompanion { * method is not typesafe: it accepts any Object, but will throw * an exception if the argument is not a java.lang.Character. * + * Runtime implementation determined by `scala.runtime.BoxesRunTime.unboxToChar`. See [[https://github.com/scala/scala src/library/scala/runtime/BoxesRunTime.java]]. + * * @param x the java.lang.Character to be unboxed. * @throws ClassCastException if the argument is not a java.lang.Character * @return the Char resulting from calling charValue() on `x` */ def unbox(x: java.lang.Object): Char = x.asInstanceOf[java.lang.Character].charValue() - /** The String representation of the scala.Char companion object. - */ + /** The String representation of the scala.Char companion object. */ override def toString = "object scala.Char" - - /** Language mandated coercions from Char to "wider" types. - */ + /** Language mandated coercions from Char to "wider" types. */ + import scala.language.implicitConversions implicit def char2int(x: Char): Int = x.toInt implicit def char2long(x: Char): Long = x.toLong implicit def char2float(x: Char): Float = x.toFloat diff --git a/src/library/scala/Console.scala b/src/library/scala/Console.scala index 5b015502ea..37127a93d5 100644 --- a/src/library/scala/Console.scala +++ b/src/library/scala/Console.scala @@ -6,16 +6,12 @@ ** |/ ** \* */ - - package scala -import java.io.{BufferedReader, InputStream, InputStreamReader, - IOException, OutputStream, PrintStream, Reader} -import java.text.MessageFormat +import java.io.{ BufferedReader, InputStream, InputStreamReader, OutputStream, PrintStream, Reader } +import scala.io.{ AnsiColor, StdIn } import scala.util.DynamicVariable - /** Implements functionality for * printing Scala values on the terminal as well as reading specific values. * Also defines constants for marking up text on ANSI terminals. @@ -23,60 +19,16 @@ import scala.util.DynamicVariable * @author Matthias Zenger * @version 1.0, 03/09/2003 */ -object Console { - - /** Foreground color for ANSI black */ - final val BLACK = "\033[30m" - /** Foreground color for ANSI red */ - final val RED = "\033[31m" - /** Foreground color for ANSI green */ - final val GREEN = "\033[32m" - /** Foreground color for ANSI yellow */ - final val YELLOW = "\033[33m" - /** Foreground color for ANSI blue */ - final val BLUE = "\033[34m" - /** Foreground color for ANSI magenta */ - final val MAGENTA = "\033[35m" - /** Foreground color for ANSI cyan */ - final val CYAN = "\033[36m" - /** Foreground color for ANSI white */ - final val WHITE = "\033[37m" - - /** Background color for ANSI black */ - final val BLACK_B = "\033[40m" - /** Background color for ANSI red */ - final val RED_B = "\033[41m" - /** Background color for ANSI green */ - final val GREEN_B = "\033[42m" - /** Background color for ANSI yellow */ - final val YELLOW_B = "\033[43m" - /** Background color for ANSI blue */ - final val BLUE_B = "\033[44m" - /** Background color for ANSI magenta */ - final val MAGENTA_B = "\033[45m" - /** Background color for ANSI cyan */ - final val CYAN_B = "\033[46m" - /** Background color for ANSI white */ - final val WHITE_B = "\033[47m" - - /** Reset ANSI styles */ - final val RESET = "\033[0m" - /** ANSI bold */ - final val BOLD = "\033[1m" - /** ANSI underlines */ - final val UNDERLINED = "\033[4m" - /** ANSI blink */ - final val BLINK = "\033[5m" - /** ANSI reversed */ - final val REVERSED = "\033[7m" - /** ANSI invisible */ - final val INVISIBLE = "\033[8m" - +object Console extends DeprecatedConsole with AnsiColor { private val outVar = new DynamicVariable[PrintStream](java.lang.System.out) private val errVar = new DynamicVariable[PrintStream](java.lang.System.err) - private val inVar = new DynamicVariable[BufferedReader]( + private val inVar = new DynamicVariable[BufferedReader]( new BufferedReader(new InputStreamReader(java.lang.System.in))) + protected def setOutDirect(out: PrintStream): Unit = outVar.value = out + protected def setErrDirect(err: PrintStream): Unit = errVar.value = err + protected def setInDirect(in: BufferedReader): Unit = inVar.value = in + /** The default output, can be overridden by `setOut` */ def out = outVar.value /** The default error, can be overridden by `setErr` */ @@ -84,12 +36,6 @@ object Console { /** The default input, can be overridden by `setIn` */ def in = inVar.value - /** Sets the default output stream. - * - * @param out the new output stream. - */ - def setOut(out: PrintStream) { outVar.value = out } - /** Sets the default output stream for the duration * of execution of one thunk. * @@ -106,13 +52,6 @@ object Console { def withOut[T](out: PrintStream)(thunk: =>T): T = outVar.withValue(out)(thunk) - /** Sets the default output stream. - * - * @param out the new output stream. - */ - def setOut(out: OutputStream): Unit = - setOut(new PrintStream(out)) - /** Sets the default output stream for the duration * of execution of one thunk. * @@ -125,13 +64,6 @@ object Console { def withOut[T](out: OutputStream)(thunk: =>T): T = withOut(new PrintStream(out))(thunk) - - /** Sets the default error stream. - * - * @param err the new error stream. - */ - def setErr(err: PrintStream) { errVar.value = err } - /** Set the default error stream for the duration * of execution of one thunk. * @example {{{ @@ -147,13 +79,6 @@ object Console { def withErr[T](err: PrintStream)(thunk: =>T): T = errVar.withValue(err)(thunk) - /** Sets the default error stream. - * - * @param err the new error stream. - */ - def setErr(err: OutputStream): Unit = - setErr(new PrintStream(err)) - /** Sets the default error stream for the duration * of execution of one thunk. * @@ -166,15 +91,6 @@ object Console { def withErr[T](err: OutputStream)(thunk: =>T): T = withErr(new PrintStream(err))(thunk) - - /** Sets the default input stream. - * - * @param reader specifies the new input stream. - */ - def setIn(reader: Reader) { - inVar.value = new BufferedReader(reader) - } - /** Sets the default input stream for the duration * of execution of one thunk. * @@ -195,14 +111,6 @@ object Console { def withIn[T](reader: Reader)(thunk: =>T): T = inVar.withValue(new BufferedReader(reader))(thunk) - /** Sets the default input stream. - * - * @param in the new input stream. - */ - def setIn(in: InputStream) { - setIn(new InputStreamReader(in)) - } - /** Sets the default input stream for the duration * of execution of one thunk. * @@ -251,218 +159,64 @@ object Console { * @throws java.lang.IllegalArgumentException if there was a problem with the format string or arguments */ def printf(text: String, args: Any*) { out.print(text format (args : _*)) } +} - /** Read a full line from the default input. Returns `null` if the end of the - * input stream has been reached. - * - * @return the string read from the terminal or null if the end of stream was reached. - */ - def readLine(): String = in.readLine() - - /** Print formatted text to the default output and read a full line from the default input. - * Returns `null` if the end of the input stream has been reached. - * - * @param text the format of the text to print out, as in `printf`. - * @param args the parameters used to instantiate the format, as in `printf`. - * @return the string read from the default input - */ - def readLine(text: String, args: Any*): String = { - printf(text, args: _*) - readLine() - } - - /** Reads a boolean value from an entire line of the default input. - * Has a fairly liberal interpretation of the input. - * - * @return the boolean value read, or false if it couldn't be converted to a boolean - * @throws java.io.EOFException if the end of the input stream has been reached. - */ - def readBoolean(): Boolean = { - val s = readLine() - if (s == null) - throw new java.io.EOFException("Console has reached end of input") - else - s.toLowerCase() match { - case "true" => true - case "t" => true - case "yes" => true - case "y" => true - case _ => false - } - } - - /** Reads a byte value from an entire line of the default input. - * - * @return the Byte that was read - * @throws java.io.EOFException if the end of the - * input stream has been reached. - * @throws java.lang.NumberFormatException if the value couldn't be converted to a Byte - */ - def readByte(): Byte = { - val s = readLine() - if (s == null) - throw new java.io.EOFException("Console has reached end of input") - else - s.toByte - } - - /** Reads a short value from an entire line of the default input. - * - * @return the short that was read - * @throws java.io.EOFException if the end of the - * input stream has been reached. - * @throws java.lang.NumberFormatException if the value couldn't be converted to a Short - */ - def readShort(): Short = { - val s = readLine() - if (s == null) - throw new java.io.EOFException("Console has reached end of input") - else - s.toShort - } - - /** Reads a char value from an entire line of the default input. - * - * @return the Char that was read - * @throws java.io.EOFException if the end of the - * input stream has been reached. - * @throws java.lang.StringIndexOutOfBoundsException if the line read from default input was empty - */ - def readChar(): Char = { - val s = readLine() - if (s == null) - throw new java.io.EOFException("Console has reached end of input") - else - s charAt 0 - } - - /** Reads an int value from an entire line of the default input. - * - * @return the Int that was read - * @throws java.io.EOFException if the end of the - * input stream has been reached. - * @throws java.lang.NumberFormatException if the value couldn't be converted to an Int - */ - def readInt(): Int = { - val s = readLine() - if (s == null) - throw new java.io.EOFException("Console has reached end of input") - else - s.toInt - } - - /** Reads an long value from an entire line of the default input. - * - * @return the Long that was read - * @throws java.io.EOFException if the end of the - * input stream has been reached. - * @throws java.lang.NumberFormatException if the value couldn't be converted to a Long - */ - def readLong(): Long = { - val s = readLine() - if (s == null) - throw new java.io.EOFException("Console has reached end of input") - else - s.toLong - } +private[scala] abstract class DeprecatedConsole { + self: Console.type => + + /** Internal usage only. */ + protected def setOutDirect(out: PrintStream): Unit + protected def setErrDirect(err: PrintStream): Unit + protected def setInDirect(in: BufferedReader): Unit + + @deprecated("Use the method in scala.io.StdIn", "2.11.0") def readBoolean(): Boolean = StdIn.readBoolean() + @deprecated("Use the method in scala.io.StdIn", "2.11.0") def readByte(): Byte = StdIn.readByte() + @deprecated("Use the method in scala.io.StdIn", "2.11.0") def readChar(): Char = StdIn.readChar() + @deprecated("Use the method in scala.io.StdIn", "2.11.0") def readDouble(): Double = StdIn.readDouble() + @deprecated("Use the method in scala.io.StdIn", "2.11.0") def readFloat(): Float = StdIn.readFloat() + @deprecated("Use the method in scala.io.StdIn", "2.11.0") def readInt(): Int = StdIn.readInt() + @deprecated("Use the method in scala.io.StdIn", "2.11.0") def readLine(): String = StdIn.readLine() + @deprecated("Use the method in scala.io.StdIn", "2.11.0") def readLine(text: String, args: Any*): String = StdIn.readLine(text, args: _*) + @deprecated("Use the method in scala.io.StdIn", "2.11.0") def readLong(): Long = StdIn.readLong() + @deprecated("Use the method in scala.io.StdIn", "2.11.0") def readShort(): Short = StdIn.readShort() + @deprecated("Use the method in scala.io.StdIn", "2.11.0") def readf(format: String): List[Any] = StdIn.readf(format) + @deprecated("Use the method in scala.io.StdIn", "2.11.0") def readf1(format: String): Any = StdIn.readf1(format) + @deprecated("Use the method in scala.io.StdIn", "2.11.0") def readf2(format: String): (Any, Any) = StdIn.readf2(format) + @deprecated("Use the method in scala.io.StdIn", "2.11.0") def readf3(format: String): (Any, Any, Any) = StdIn.readf3(format) - /** Reads a float value from an entire line of the default input. - * @return the Float that was read. - * @throws java.io.EOFException if the end of the - * input stream has been reached. - * @throws java.lang.NumberFormatException if the value couldn't be converted to a Float + /** Sets the default output stream. * + * @param out the new output stream. */ - def readFloat(): Float = { - val s = readLine() - if (s == null) - throw new java.io.EOFException("Console has reached end of input") - else - s.toFloat - } + @deprecated("Use withOut", "2.11.0") def setOut(out: PrintStream): Unit = setOutDirect(out) - /** Reads a double value from an entire line of the default input. + /** Sets the default output stream. * - * @return the Double that was read. - * @throws java.io.EOFException if the end of the - * input stream has been reached. - * @throws java.lang.NumberFormatException if the value couldn't be converted to a Float + * @param out the new output stream. */ - def readDouble(): Double = { - val s = readLine() - if (s == null) - throw new java.io.EOFException("Console has reached end of input") - else - s.toDouble - } + @deprecated("Use withOut", "2.11.0") def setOut(out: OutputStream): Unit = setOutDirect(new PrintStream(out)) - /** Reads in some structured input (from the default input), specified by - * a format specifier. See class `java.text.MessageFormat` for details of - * the format specification. + /** Sets the default error stream. * - * @param format the format of the input. - * @return a list of all extracted values. - * @throws java.io.EOFException if the end of the input stream has been - * reached. + * @param err the new error stream. */ - def readf(format: String): List[Any] = { - val s = readLine() - if (s == null) - throw new java.io.EOFException("Console has reached end of input") - else - textComponents(new MessageFormat(format).parse(s)) - } + @deprecated("Use withErr", "2.11.0") def setErr(err: PrintStream): Unit = setErrDirect(err) - /** Reads in some structured input (from the default input), specified by - * a format specifier, returning only the first value extracted, according - * to the format specification. + /** Sets the default error stream. * - * @param format format string, as accepted by `readf`. - * @return The first value that was extracted from the input + * @param err the new error stream. */ - def readf1(format: String): Any = readf(format).head + @deprecated("Use withErr", "2.11.0") def setErr(err: OutputStream): Unit = setErrDirect(new PrintStream(err)) - /** Reads in some structured input (from the default input), specified - * by a format specifier, returning only the first two values extracted, - * according to the format specification. + /** Sets the default input stream. * - * @param format format string, as accepted by `readf`. - * @return A [[scala.Tuple2]] containing the first two values extracted + * @param reader specifies the new input stream. */ - def readf2(format: String): (Any, Any) = { - val res = readf(format) - (res.head, res.tail.head) - } + @deprecated("Use withIn", "2.11.0") def setIn(reader: Reader): Unit = setInDirect(new BufferedReader(reader)) - /** Reads in some structured input (from the default input), specified - * by a format specifier, returning only the first three values extracted, - * according to the format specification. + /** Sets the default input stream. * - * @param format format string, as accepted by `readf`. - * @return A [[scala.Tuple3]] containing the first three values extracted + * @param in the new input stream. */ - def readf3(format: String): (Any, Any, Any) = { - val res = readf(format) - (res.head, res.tail.head, res.tail.tail.head) - } - - private def textComponents(a: Array[AnyRef]): List[Any] = { - var i: Int = a.length - 1 - var res: List[Any] = Nil - while (i >= 0) { - res = (a(i) match { - case x: java.lang.Boolean => x.booleanValue() - case x: java.lang.Byte => x.byteValue() - case x: java.lang.Short => x.shortValue() - case x: java.lang.Character => x.charValue() - case x: java.lang.Integer => x.intValue() - case x: java.lang.Long => x.longValue() - case x: java.lang.Float => x.floatValue() - case x: java.lang.Double => x.doubleValue() - case x => x - }) :: res; - i -= 1 - } - res - } + @deprecated("Use withIn", "2.11.0") def setIn(in: InputStream): Unit = setInDirect(new BufferedReader(new InputStreamReader(in))) } diff --git a/src/library/scala/DelayedInit.scala b/src/library/scala/DelayedInit.scala index 12793e6aa1..7f976b073f 100644 --- a/src/library/scala/DelayedInit.scala +++ b/src/library/scala/DelayedInit.scala @@ -8,7 +8,7 @@ package scala -/** Classes and objects (but note, not traits) inheriting the `DelayedInit` +/** Classes and objects (but note, not traits) inheriting the `DelayedInit` * marker trait will have their initialization code rewritten as follows: * `code` becomes `delayedInit(code)`. * @@ -32,7 +32,7 @@ package scala * val c = new C * } * }}} - * + * * Should result in the following being printed: * {{{ * dummy text, printed before initialization of C @@ -43,6 +43,7 @@ package scala * * @author Martin Odersky */ +@deprecated("DelayedInit semantics can be surprising. Support for `App` will continue.\nSee the release notes for more details: https://github.com/scala/scala/releases/tag/v2.11.0-RC1", "2.11.0") trait DelayedInit { def delayedInit(x: => Unit): Unit }
\ No newline at end of file diff --git a/src/library/scala/Double.scala b/src/library/scala/Double.scala index f058d7c26b..a58fa3ed25 100644 --- a/src/library/scala/Double.scala +++ b/src/library/scala/Double.scala @@ -1,17 +1,17 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** +** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** \* */ -// DO NOT EDIT, CHANGES WILL BE LOST. +// DO NOT EDIT, CHANGES WILL BE LOST +// This auto-generated code can be modified in scala.tools.cmd.gen. +// Afterwards, running tools/codegen-anyvals regenerates this source file. package scala -import scala.language.implicitConversions - /** `Double`, a 64-bit IEEE-754 floating point number (equivalent to Java's `double` primitive type) is a * subtype of [[scala.AnyVal]]. Instances of `Double` are not * represented by an object in the underlying runtime system. @@ -28,334 +28,176 @@ final abstract class Double private extends AnyVal { def toFloat: Float def toDouble: Double - /** - * Returns this value, unmodified. - */ + /** Returns this value, unmodified. */ def unary_+ : Double - /** - * Returns the negation of this value. - */ + /** Returns the negation of this value. */ def unary_- : Double def +(x: String): String - /** - * Returns `true` if this value is equal to x, `false` otherwise. - */ + /** Returns `true` if this value is equal to x, `false` otherwise. */ def ==(x: Byte): Boolean - /** - * Returns `true` if this value is equal to x, `false` otherwise. - */ + /** Returns `true` if this value is equal to x, `false` otherwise. */ def ==(x: Short): Boolean - /** - * Returns `true` if this value is equal to x, `false` otherwise. - */ + /** Returns `true` if this value is equal to x, `false` otherwise. */ def ==(x: Char): Boolean - /** - * Returns `true` if this value is equal to x, `false` otherwise. - */ + /** Returns `true` if this value is equal to x, `false` otherwise. */ def ==(x: Int): Boolean - /** - * Returns `true` if this value is equal to x, `false` otherwise. - */ + /** Returns `true` if this value is equal to x, `false` otherwise. */ def ==(x: Long): Boolean - /** - * Returns `true` if this value is equal to x, `false` otherwise. - */ + /** Returns `true` if this value is equal to x, `false` otherwise. */ def ==(x: Float): Boolean - /** - * Returns `true` if this value is equal to x, `false` otherwise. - */ + /** Returns `true` if this value is equal to x, `false` otherwise. */ def ==(x: Double): Boolean - /** - * Returns `true` if this value is not equal to x, `false` otherwise. - */ + /** Returns `true` if this value is not equal to x, `false` otherwise. */ def !=(x: Byte): Boolean - /** - * Returns `true` if this value is not equal to x, `false` otherwise. - */ + /** Returns `true` if this value is not equal to x, `false` otherwise. */ def !=(x: Short): Boolean - /** - * Returns `true` if this value is not equal to x, `false` otherwise. - */ + /** Returns `true` if this value is not equal to x, `false` otherwise. */ def !=(x: Char): Boolean - /** - * Returns `true` if this value is not equal to x, `false` otherwise. - */ + /** Returns `true` if this value is not equal to x, `false` otherwise. */ def !=(x: Int): Boolean - /** - * Returns `true` if this value is not equal to x, `false` otherwise. - */ + /** Returns `true` if this value is not equal to x, `false` otherwise. */ def !=(x: Long): Boolean - /** - * Returns `true` if this value is not equal to x, `false` otherwise. - */ + /** Returns `true` if this value is not equal to x, `false` otherwise. */ def !=(x: Float): Boolean - /** - * Returns `true` if this value is not equal to x, `false` otherwise. - */ + /** Returns `true` if this value is not equal to x, `false` otherwise. */ def !=(x: Double): Boolean - /** - * Returns `true` if this value is less than x, `false` otherwise. - */ + /** Returns `true` if this value is less than x, `false` otherwise. */ def <(x: Byte): Boolean - /** - * Returns `true` if this value is less than x, `false` otherwise. - */ + /** Returns `true` if this value is less than x, `false` otherwise. */ def <(x: Short): Boolean - /** - * Returns `true` if this value is less than x, `false` otherwise. - */ + /** Returns `true` if this value is less than x, `false` otherwise. */ def <(x: Char): Boolean - /** - * Returns `true` if this value is less than x, `false` otherwise. - */ + /** Returns `true` if this value is less than x, `false` otherwise. */ def <(x: Int): Boolean - /** - * Returns `true` if this value is less than x, `false` otherwise. - */ + /** Returns `true` if this value is less than x, `false` otherwise. */ def <(x: Long): Boolean - /** - * Returns `true` if this value is less than x, `false` otherwise. - */ + /** Returns `true` if this value is less than x, `false` otherwise. */ def <(x: Float): Boolean - /** - * Returns `true` if this value is less than x, `false` otherwise. - */ + /** Returns `true` if this value is less than x, `false` otherwise. */ def <(x: Double): Boolean - /** - * Returns `true` if this value is less than or equal to x, `false` otherwise. - */ + /** Returns `true` if this value is less than or equal to x, `false` otherwise. */ def <=(x: Byte): Boolean - /** - * Returns `true` if this value is less than or equal to x, `false` otherwise. - */ + /** Returns `true` if this value is less than or equal to x, `false` otherwise. */ def <=(x: Short): Boolean - /** - * Returns `true` if this value is less than or equal to x, `false` otherwise. - */ + /** Returns `true` if this value is less than or equal to x, `false` otherwise. */ def <=(x: Char): Boolean - /** - * Returns `true` if this value is less than or equal to x, `false` otherwise. - */ + /** Returns `true` if this value is less than or equal to x, `false` otherwise. */ def <=(x: Int): Boolean - /** - * Returns `true` if this value is less than or equal to x, `false` otherwise. - */ + /** Returns `true` if this value is less than or equal to x, `false` otherwise. */ def <=(x: Long): Boolean - /** - * Returns `true` if this value is less than or equal to x, `false` otherwise. - */ + /** Returns `true` if this value is less than or equal to x, `false` otherwise. */ def <=(x: Float): Boolean - /** - * Returns `true` if this value is less than or equal to x, `false` otherwise. - */ + /** Returns `true` if this value is less than or equal to x, `false` otherwise. */ def <=(x: Double): Boolean - /** - * Returns `true` if this value is greater than x, `false` otherwise. - */ + /** Returns `true` if this value is greater than x, `false` otherwise. */ def >(x: Byte): Boolean - /** - * Returns `true` if this value is greater than x, `false` otherwise. - */ + /** Returns `true` if this value is greater than x, `false` otherwise. */ def >(x: Short): Boolean - /** - * Returns `true` if this value is greater than x, `false` otherwise. - */ + /** Returns `true` if this value is greater than x, `false` otherwise. */ def >(x: Char): Boolean - /** - * Returns `true` if this value is greater than x, `false` otherwise. - */ + /** Returns `true` if this value is greater than x, `false` otherwise. */ def >(x: Int): Boolean - /** - * Returns `true` if this value is greater than x, `false` otherwise. - */ + /** Returns `true` if this value is greater than x, `false` otherwise. */ def >(x: Long): Boolean - /** - * Returns `true` if this value is greater than x, `false` otherwise. - */ + /** Returns `true` if this value is greater than x, `false` otherwise. */ def >(x: Float): Boolean - /** - * Returns `true` if this value is greater than x, `false` otherwise. - */ + /** Returns `true` if this value is greater than x, `false` otherwise. */ def >(x: Double): Boolean - /** - * Returns `true` if this value is greater than or equal to x, `false` otherwise. - */ + /** Returns `true` if this value is greater than or equal to x, `false` otherwise. */ def >=(x: Byte): Boolean - /** - * Returns `true` if this value is greater than or equal to x, `false` otherwise. - */ + /** Returns `true` if this value is greater than or equal to x, `false` otherwise. */ def >=(x: Short): Boolean - /** - * Returns `true` if this value is greater than or equal to x, `false` otherwise. - */ + /** Returns `true` if this value is greater than or equal to x, `false` otherwise. */ def >=(x: Char): Boolean - /** - * Returns `true` if this value is greater than or equal to x, `false` otherwise. - */ + /** Returns `true` if this value is greater than or equal to x, `false` otherwise. */ def >=(x: Int): Boolean - /** - * Returns `true` if this value is greater than or equal to x, `false` otherwise. - */ + /** Returns `true` if this value is greater than or equal to x, `false` otherwise. */ def >=(x: Long): Boolean - /** - * Returns `true` if this value is greater than or equal to x, `false` otherwise. - */ + /** Returns `true` if this value is greater than or equal to x, `false` otherwise. */ def >=(x: Float): Boolean - /** - * Returns `true` if this value is greater than or equal to x, `false` otherwise. - */ + /** Returns `true` if this value is greater than or equal to x, `false` otherwise. */ def >=(x: Double): Boolean - /** - * Returns the sum of this value and `x`. - */ + /** Returns the sum of this value and `x`. */ def +(x: Byte): Double - /** - * Returns the sum of this value and `x`. - */ + /** Returns the sum of this value and `x`. */ def +(x: Short): Double - /** - * Returns the sum of this value and `x`. - */ + /** Returns the sum of this value and `x`. */ def +(x: Char): Double - /** - * Returns the sum of this value and `x`. - */ + /** Returns the sum of this value and `x`. */ def +(x: Int): Double - /** - * Returns the sum of this value and `x`. - */ + /** Returns the sum of this value and `x`. */ def +(x: Long): Double - /** - * Returns the sum of this value and `x`. - */ + /** Returns the sum of this value and `x`. */ def +(x: Float): Double - /** - * Returns the sum of this value and `x`. - */ + /** Returns the sum of this value and `x`. */ def +(x: Double): Double - /** - * Returns the difference of this value and `x`. - */ + /** Returns the difference of this value and `x`. */ def -(x: Byte): Double - /** - * Returns the difference of this value and `x`. - */ + /** Returns the difference of this value and `x`. */ def -(x: Short): Double - /** - * Returns the difference of this value and `x`. - */ + /** Returns the difference of this value and `x`. */ def -(x: Char): Double - /** - * Returns the difference of this value and `x`. - */ + /** Returns the difference of this value and `x`. */ def -(x: Int): Double - /** - * Returns the difference of this value and `x`. - */ + /** Returns the difference of this value and `x`. */ def -(x: Long): Double - /** - * Returns the difference of this value and `x`. - */ + /** Returns the difference of this value and `x`. */ def -(x: Float): Double - /** - * Returns the difference of this value and `x`. - */ + /** Returns the difference of this value and `x`. */ def -(x: Double): Double - /** - * Returns the product of this value and `x`. - */ + /** Returns the product of this value and `x`. */ def *(x: Byte): Double - /** - * Returns the product of this value and `x`. - */ + /** Returns the product of this value and `x`. */ def *(x: Short): Double - /** - * Returns the product of this value and `x`. - */ + /** Returns the product of this value and `x`. */ def *(x: Char): Double - /** - * Returns the product of this value and `x`. - */ + /** Returns the product of this value and `x`. */ def *(x: Int): Double - /** - * Returns the product of this value and `x`. - */ + /** Returns the product of this value and `x`. */ def *(x: Long): Double - /** - * Returns the product of this value and `x`. - */ + /** Returns the product of this value and `x`. */ def *(x: Float): Double - /** - * Returns the product of this value and `x`. - */ + /** Returns the product of this value and `x`. */ def *(x: Double): Double - /** - * Returns the quotient of this value and `x`. - */ + /** Returns the quotient of this value and `x`. */ def /(x: Byte): Double - /** - * Returns the quotient of this value and `x`. - */ + /** Returns the quotient of this value and `x`. */ def /(x: Short): Double - /** - * Returns the quotient of this value and `x`. - */ + /** Returns the quotient of this value and `x`. */ def /(x: Char): Double - /** - * Returns the quotient of this value and `x`. - */ + /** Returns the quotient of this value and `x`. */ def /(x: Int): Double - /** - * Returns the quotient of this value and `x`. - */ + /** Returns the quotient of this value and `x`. */ def /(x: Long): Double - /** - * Returns the quotient of this value and `x`. - */ + /** Returns the quotient of this value and `x`. */ def /(x: Float): Double - /** - * Returns the quotient of this value and `x`. - */ + /** Returns the quotient of this value and `x`. */ def /(x: Double): Double - /** - * Returns the remainder of the division of this value by `x`. - */ + /** Returns the remainder of the division of this value by `x`. */ def %(x: Byte): Double - /** - * Returns the remainder of the division of this value by `x`. - */ + /** Returns the remainder of the division of this value by `x`. */ def %(x: Short): Double - /** - * Returns the remainder of the division of this value by `x`. - */ + /** Returns the remainder of the division of this value by `x`. */ def %(x: Char): Double - /** - * Returns the remainder of the division of this value by `x`. - */ + /** Returns the remainder of the division of this value by `x`. */ def %(x: Int): Double - /** - * Returns the remainder of the division of this value by `x`. - */ + /** Returns the remainder of the division of this value by `x`. */ def %(x: Long): Double - /** - * Returns the remainder of the division of this value by `x`. - */ + /** Returns the remainder of the division of this value by `x`. */ def %(x: Float): Double - /** - * Returns the remainder of the division of this value by `x`. - */ + /** Returns the remainder of the division of this value by `x`. */ def %(x: Double): Double override def getClass(): Class[Double] = null @@ -382,6 +224,8 @@ object Double extends AnyValCompanion { /** Transform a value type into a boxed reference type. * + * Runtime implementation determined by `scala.runtime.BoxesRunTime.boxToDouble`. See [[https://github.com/scala/scala src/library/scala/runtime/BoxesRunTime.java]]. + * * @param x the Double to be boxed * @return a java.lang.Double offering `x` as its underlying value. */ @@ -391,14 +235,15 @@ object Double extends AnyValCompanion { * method is not typesafe: it accepts any Object, but will throw * an exception if the argument is not a java.lang.Double. * + * Runtime implementation determined by `scala.runtime.BoxesRunTime.unboxToDouble`. See [[https://github.com/scala/scala src/library/scala/runtime/BoxesRunTime.java]]. + * * @param x the java.lang.Double to be unboxed. * @throws ClassCastException if the argument is not a java.lang.Double * @return the Double resulting from calling doubleValue() on `x` */ def unbox(x: java.lang.Object): Double = x.asInstanceOf[java.lang.Double].doubleValue() - /** The String representation of the scala.Double companion object. - */ + /** The String representation of the scala.Double companion object. */ override def toString = "object scala.Double" } diff --git a/src/library/scala/Enumeration.scala b/src/library/scala/Enumeration.scala index 47d7840e27..d4b9c17eab 100644 --- a/src/library/scala/Enumeration.scala +++ b/src/library/scala/Enumeration.scala @@ -11,7 +11,7 @@ package scala import scala.collection.{ mutable, immutable, generic, SortedSetLike, AbstractSet } import java.lang.reflect.{ Modifier, Method => JMethod, Field => JField } import scala.reflect.NameTransformer._ -import java.util.regex.Pattern +import scala.util.matching.Regex /** Defines a finite set of values specific to the enumeration. Typically * these values enumerate all possible forms something can take and provide @@ -56,14 +56,6 @@ abstract class Enumeration (initial: Int) extends Serializable { def this() = this(0) - @deprecated("Names should be specified individually or discovered via reflection", "2.10.0") - def this(initial: Int, names: String*) = { - this(initial) - this.nextName = names.iterator - } - @deprecated("Names should be specified individually or discovered via reflection", "2.10.0") - def this(names: String*) = this(0, names: _*) - /* Note that `readResolve` cannot be private, since otherwise the JVM does not invoke it when deserializing subclasses. */ protected def readResolve(): AnyRef = thisenum.getClass.getField(MODULE_INSTANCE_NAME).get(null) @@ -71,8 +63,8 @@ abstract class Enumeration (initial: Int) extends Serializable { /** The name of this enumeration. */ override def toString = - ((getClass.getName stripSuffix MODULE_SUFFIX_STRING split '.').last split - Pattern.quote(NAME_JOIN_STRING)).last + ((getClass.getName stripSuffix MODULE_SUFFIX_STRING split '.').last split + Regex.quote(NAME_JOIN_STRING)).last /** The mapping from the integer used to identify values to the actual * values. */ @@ -103,7 +95,7 @@ abstract class Enumeration (initial: Int) extends Serializable { protected var nextName: Iterator[String] = _ private def nextNameOrNull = - if (nextName != null && nextName.hasNext) nextName.next else null + if (nextName != null && nextName.hasNext) nextName.next() else null /** The highest integer amongst those used to identify values in this * enumeration. */ @@ -126,7 +118,7 @@ abstract class Enumeration (initial: Int) extends Serializable { * * @param s an `Enumeration` name * @return the `Value` of this `Enumeration` if its name matches `s` - * @throws java.util.NoSuchElementException if no `Value` with a matching + * @throws NoSuchElementException if no `Value` with a matching * name is in this `Enumeration` */ final def withName(s: String): Value = values.find(_.toString == s).get @@ -262,7 +254,8 @@ abstract class Enumeration (initial: Int) extends Serializable { def contains(v: Value) = nnIds contains (v.id - bottomId) def + (value: Value) = new ValueSet(nnIds + (value.id - bottomId)) def - (value: Value) = new ValueSet(nnIds - (value.id - bottomId)) - def iterator = nnIds.iterator map (id => thisenum.apply(id + bottomId)) + def iterator = nnIds.iterator map (id => thisenum.apply(bottomId + id)) + override def keysIteratorFrom(start: Value) = nnIds keysIteratorFrom start.id map (id => thisenum.apply(bottomId + id)) override def stringPrefix = thisenum + ".ValueSet" /** Creates a bit mask for the zero-adjusted ids in this set as a * new array of longs */ @@ -284,7 +277,7 @@ abstract class Enumeration (initial: Int) extends Serializable { def newBuilder: mutable.Builder[Value, ValueSet] = new mutable.Builder[Value, ValueSet] { private[this] val b = new mutable.BitSet def += (x: Value) = { b += (x.id - bottomId); this } - def clear() = b.clear + def clear() = b.clear() def result() = new ValueSet(b.toImmutable) } /** The implicit builder for value sets */ diff --git a/src/library/scala/Float.scala b/src/library/scala/Float.scala index d942acec23..3c59057a8d 100644 --- a/src/library/scala/Float.scala +++ b/src/library/scala/Float.scala @@ -1,17 +1,17 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** +** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** \* */ -// DO NOT EDIT, CHANGES WILL BE LOST. +// DO NOT EDIT, CHANGES WILL BE LOST +// This auto-generated code can be modified in scala.tools.cmd.gen. +// Afterwards, running tools/codegen-anyvals regenerates this source file. package scala -import scala.language.implicitConversions - /** `Float`, a 32-bit IEEE-754 floating point number (equivalent to Java's `float` primitive type) is a * subtype of [[scala.AnyVal]]. Instances of `Float` are not * represented by an object in the underlying runtime system. @@ -28,334 +28,176 @@ final abstract class Float private extends AnyVal { def toFloat: Float def toDouble: Double - /** - * Returns this value, unmodified. - */ + /** Returns this value, unmodified. */ def unary_+ : Float - /** - * Returns the negation of this value. - */ + /** Returns the negation of this value. */ def unary_- : Float def +(x: String): String - /** - * Returns `true` if this value is equal to x, `false` otherwise. - */ + /** Returns `true` if this value is equal to x, `false` otherwise. */ def ==(x: Byte): Boolean - /** - * Returns `true` if this value is equal to x, `false` otherwise. - */ + /** Returns `true` if this value is equal to x, `false` otherwise. */ def ==(x: Short): Boolean - /** - * Returns `true` if this value is equal to x, `false` otherwise. - */ + /** Returns `true` if this value is equal to x, `false` otherwise. */ def ==(x: Char): Boolean - /** - * Returns `true` if this value is equal to x, `false` otherwise. - */ + /** Returns `true` if this value is equal to x, `false` otherwise. */ def ==(x: Int): Boolean - /** - * Returns `true` if this value is equal to x, `false` otherwise. - */ + /** Returns `true` if this value is equal to x, `false` otherwise. */ def ==(x: Long): Boolean - /** - * Returns `true` if this value is equal to x, `false` otherwise. - */ + /** Returns `true` if this value is equal to x, `false` otherwise. */ def ==(x: Float): Boolean - /** - * Returns `true` if this value is equal to x, `false` otherwise. - */ + /** Returns `true` if this value is equal to x, `false` otherwise. */ def ==(x: Double): Boolean - /** - * Returns `true` if this value is not equal to x, `false` otherwise. - */ + /** Returns `true` if this value is not equal to x, `false` otherwise. */ def !=(x: Byte): Boolean - /** - * Returns `true` if this value is not equal to x, `false` otherwise. - */ + /** Returns `true` if this value is not equal to x, `false` otherwise. */ def !=(x: Short): Boolean - /** - * Returns `true` if this value is not equal to x, `false` otherwise. - */ + /** Returns `true` if this value is not equal to x, `false` otherwise. */ def !=(x: Char): Boolean - /** - * Returns `true` if this value is not equal to x, `false` otherwise. - */ + /** Returns `true` if this value is not equal to x, `false` otherwise. */ def !=(x: Int): Boolean - /** - * Returns `true` if this value is not equal to x, `false` otherwise. - */ + /** Returns `true` if this value is not equal to x, `false` otherwise. */ def !=(x: Long): Boolean - /** - * Returns `true` if this value is not equal to x, `false` otherwise. - */ + /** Returns `true` if this value is not equal to x, `false` otherwise. */ def !=(x: Float): Boolean - /** - * Returns `true` if this value is not equal to x, `false` otherwise. - */ + /** Returns `true` if this value is not equal to x, `false` otherwise. */ def !=(x: Double): Boolean - /** - * Returns `true` if this value is less than x, `false` otherwise. - */ + /** Returns `true` if this value is less than x, `false` otherwise. */ def <(x: Byte): Boolean - /** - * Returns `true` if this value is less than x, `false` otherwise. - */ + /** Returns `true` if this value is less than x, `false` otherwise. */ def <(x: Short): Boolean - /** - * Returns `true` if this value is less than x, `false` otherwise. - */ + /** Returns `true` if this value is less than x, `false` otherwise. */ def <(x: Char): Boolean - /** - * Returns `true` if this value is less than x, `false` otherwise. - */ + /** Returns `true` if this value is less than x, `false` otherwise. */ def <(x: Int): Boolean - /** - * Returns `true` if this value is less than x, `false` otherwise. - */ + /** Returns `true` if this value is less than x, `false` otherwise. */ def <(x: Long): Boolean - /** - * Returns `true` if this value is less than x, `false` otherwise. - */ + /** Returns `true` if this value is less than x, `false` otherwise. */ def <(x: Float): Boolean - /** - * Returns `true` if this value is less than x, `false` otherwise. - */ + /** Returns `true` if this value is less than x, `false` otherwise. */ def <(x: Double): Boolean - /** - * Returns `true` if this value is less than or equal to x, `false` otherwise. - */ + /** Returns `true` if this value is less than or equal to x, `false` otherwise. */ def <=(x: Byte): Boolean - /** - * Returns `true` if this value is less than or equal to x, `false` otherwise. - */ + /** Returns `true` if this value is less than or equal to x, `false` otherwise. */ def <=(x: Short): Boolean - /** - * Returns `true` if this value is less than or equal to x, `false` otherwise. - */ + /** Returns `true` if this value is less than or equal to x, `false` otherwise. */ def <=(x: Char): Boolean - /** - * Returns `true` if this value is less than or equal to x, `false` otherwise. - */ + /** Returns `true` if this value is less than or equal to x, `false` otherwise. */ def <=(x: Int): Boolean - /** - * Returns `true` if this value is less than or equal to x, `false` otherwise. - */ + /** Returns `true` if this value is less than or equal to x, `false` otherwise. */ def <=(x: Long): Boolean - /** - * Returns `true` if this value is less than or equal to x, `false` otherwise. - */ + /** Returns `true` if this value is less than or equal to x, `false` otherwise. */ def <=(x: Float): Boolean - /** - * Returns `true` if this value is less than or equal to x, `false` otherwise. - */ + /** Returns `true` if this value is less than or equal to x, `false` otherwise. */ def <=(x: Double): Boolean - /** - * Returns `true` if this value is greater than x, `false` otherwise. - */ + /** Returns `true` if this value is greater than x, `false` otherwise. */ def >(x: Byte): Boolean - /** - * Returns `true` if this value is greater than x, `false` otherwise. - */ + /** Returns `true` if this value is greater than x, `false` otherwise. */ def >(x: Short): Boolean - /** - * Returns `true` if this value is greater than x, `false` otherwise. - */ + /** Returns `true` if this value is greater than x, `false` otherwise. */ def >(x: Char): Boolean - /** - * Returns `true` if this value is greater than x, `false` otherwise. - */ + /** Returns `true` if this value is greater than x, `false` otherwise. */ def >(x: Int): Boolean - /** - * Returns `true` if this value is greater than x, `false` otherwise. - */ + /** Returns `true` if this value is greater than x, `false` otherwise. */ def >(x: Long): Boolean - /** - * Returns `true` if this value is greater than x, `false` otherwise. - */ + /** Returns `true` if this value is greater than x, `false` otherwise. */ def >(x: Float): Boolean - /** - * Returns `true` if this value is greater than x, `false` otherwise. - */ + /** Returns `true` if this value is greater than x, `false` otherwise. */ def >(x: Double): Boolean - /** - * Returns `true` if this value is greater than or equal to x, `false` otherwise. - */ + /** Returns `true` if this value is greater than or equal to x, `false` otherwise. */ def >=(x: Byte): Boolean - /** - * Returns `true` if this value is greater than or equal to x, `false` otherwise. - */ + /** Returns `true` if this value is greater than or equal to x, `false` otherwise. */ def >=(x: Short): Boolean - /** - * Returns `true` if this value is greater than or equal to x, `false` otherwise. - */ + /** Returns `true` if this value is greater than or equal to x, `false` otherwise. */ def >=(x: Char): Boolean - /** - * Returns `true` if this value is greater than or equal to x, `false` otherwise. - */ + /** Returns `true` if this value is greater than or equal to x, `false` otherwise. */ def >=(x: Int): Boolean - /** - * Returns `true` if this value is greater than or equal to x, `false` otherwise. - */ + /** Returns `true` if this value is greater than or equal to x, `false` otherwise. */ def >=(x: Long): Boolean - /** - * Returns `true` if this value is greater than or equal to x, `false` otherwise. - */ + /** Returns `true` if this value is greater than or equal to x, `false` otherwise. */ def >=(x: Float): Boolean - /** - * Returns `true` if this value is greater than or equal to x, `false` otherwise. - */ + /** Returns `true` if this value is greater than or equal to x, `false` otherwise. */ def >=(x: Double): Boolean - /** - * Returns the sum of this value and `x`. - */ + /** Returns the sum of this value and `x`. */ def +(x: Byte): Float - /** - * Returns the sum of this value and `x`. - */ + /** Returns the sum of this value and `x`. */ def +(x: Short): Float - /** - * Returns the sum of this value and `x`. - */ + /** Returns the sum of this value and `x`. */ def +(x: Char): Float - /** - * Returns the sum of this value and `x`. - */ + /** Returns the sum of this value and `x`. */ def +(x: Int): Float - /** - * Returns the sum of this value and `x`. - */ + /** Returns the sum of this value and `x`. */ def +(x: Long): Float - /** - * Returns the sum of this value and `x`. - */ + /** Returns the sum of this value and `x`. */ def +(x: Float): Float - /** - * Returns the sum of this value and `x`. - */ + /** Returns the sum of this value and `x`. */ def +(x: Double): Double - /** - * Returns the difference of this value and `x`. - */ + /** Returns the difference of this value and `x`. */ def -(x: Byte): Float - /** - * Returns the difference of this value and `x`. - */ + /** Returns the difference of this value and `x`. */ def -(x: Short): Float - /** - * Returns the difference of this value and `x`. - */ + /** Returns the difference of this value and `x`. */ def -(x: Char): Float - /** - * Returns the difference of this value and `x`. - */ + /** Returns the difference of this value and `x`. */ def -(x: Int): Float - /** - * Returns the difference of this value and `x`. - */ + /** Returns the difference of this value and `x`. */ def -(x: Long): Float - /** - * Returns the difference of this value and `x`. - */ + /** Returns the difference of this value and `x`. */ def -(x: Float): Float - /** - * Returns the difference of this value and `x`. - */ + /** Returns the difference of this value and `x`. */ def -(x: Double): Double - /** - * Returns the product of this value and `x`. - */ + /** Returns the product of this value and `x`. */ def *(x: Byte): Float - /** - * Returns the product of this value and `x`. - */ + /** Returns the product of this value and `x`. */ def *(x: Short): Float - /** - * Returns the product of this value and `x`. - */ + /** Returns the product of this value and `x`. */ def *(x: Char): Float - /** - * Returns the product of this value and `x`. - */ + /** Returns the product of this value and `x`. */ def *(x: Int): Float - /** - * Returns the product of this value and `x`. - */ + /** Returns the product of this value and `x`. */ def *(x: Long): Float - /** - * Returns the product of this value and `x`. - */ + /** Returns the product of this value and `x`. */ def *(x: Float): Float - /** - * Returns the product of this value and `x`. - */ + /** Returns the product of this value and `x`. */ def *(x: Double): Double - /** - * Returns the quotient of this value and `x`. - */ + /** Returns the quotient of this value and `x`. */ def /(x: Byte): Float - /** - * Returns the quotient of this value and `x`. - */ + /** Returns the quotient of this value and `x`. */ def /(x: Short): Float - /** - * Returns the quotient of this value and `x`. - */ + /** Returns the quotient of this value and `x`. */ def /(x: Char): Float - /** - * Returns the quotient of this value and `x`. - */ + /** Returns the quotient of this value and `x`. */ def /(x: Int): Float - /** - * Returns the quotient of this value and `x`. - */ + /** Returns the quotient of this value and `x`. */ def /(x: Long): Float - /** - * Returns the quotient of this value and `x`. - */ + /** Returns the quotient of this value and `x`. */ def /(x: Float): Float - /** - * Returns the quotient of this value and `x`. - */ + /** Returns the quotient of this value and `x`. */ def /(x: Double): Double - /** - * Returns the remainder of the division of this value by `x`. - */ + /** Returns the remainder of the division of this value by `x`. */ def %(x: Byte): Float - /** - * Returns the remainder of the division of this value by `x`. - */ + /** Returns the remainder of the division of this value by `x`. */ def %(x: Short): Float - /** - * Returns the remainder of the division of this value by `x`. - */ + /** Returns the remainder of the division of this value by `x`. */ def %(x: Char): Float - /** - * Returns the remainder of the division of this value by `x`. - */ + /** Returns the remainder of the division of this value by `x`. */ def %(x: Int): Float - /** - * Returns the remainder of the division of this value by `x`. - */ + /** Returns the remainder of the division of this value by `x`. */ def %(x: Long): Float - /** - * Returns the remainder of the division of this value by `x`. - */ + /** Returns the remainder of the division of this value by `x`. */ def %(x: Float): Float - /** - * Returns the remainder of the division of this value by `x`. - */ + /** Returns the remainder of the division of this value by `x`. */ def %(x: Double): Double override def getClass(): Class[Float] = null @@ -382,6 +224,8 @@ object Float extends AnyValCompanion { /** Transform a value type into a boxed reference type. * + * Runtime implementation determined by `scala.runtime.BoxesRunTime.boxToFloat`. See [[https://github.com/scala/scala src/library/scala/runtime/BoxesRunTime.java]]. + * * @param x the Float to be boxed * @return a java.lang.Float offering `x` as its underlying value. */ @@ -391,18 +235,18 @@ object Float extends AnyValCompanion { * method is not typesafe: it accepts any Object, but will throw * an exception if the argument is not a java.lang.Float. * + * Runtime implementation determined by `scala.runtime.BoxesRunTime.unboxToFloat`. See [[https://github.com/scala/scala src/library/scala/runtime/BoxesRunTime.java]]. + * * @param x the java.lang.Float to be unboxed. * @throws ClassCastException if the argument is not a java.lang.Float * @return the Float resulting from calling floatValue() on `x` */ def unbox(x: java.lang.Object): Float = x.asInstanceOf[java.lang.Float].floatValue() - /** The String representation of the scala.Float companion object. - */ + /** The String representation of the scala.Float companion object. */ override def toString = "object scala.Float" - - /** Language mandated coercions from Float to "wider" types. - */ + /** Language mandated coercions from Float to "wider" types. */ + import scala.language.implicitConversions implicit def float2double(x: Float): Double = x.toDouble } diff --git a/src/library/scala/Function0.scala b/src/library/scala/Function0.scala index 5f87b38057..e13aaad7bc 100644 --- a/src/library/scala/Function0.scala +++ b/src/library/scala/Function0.scala @@ -1,12 +1,12 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** +** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** \* */ // GENERATED CODE: DO NOT EDIT. -// genprod generated these sources at: Tue Aug 07 11:54:44 CEST 2012 +// genprod generated these sources at: Sun Sep 15 20:42:00 CEST 2013 package scala diff --git a/src/library/scala/Function1.scala b/src/library/scala/Function1.scala index 22393c65dd..620dcc19aa 100644 --- a/src/library/scala/Function1.scala +++ b/src/library/scala/Function1.scala @@ -1,6 +1,6 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** +** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** @@ -32,7 +32,7 @@ package scala */ @annotation.implicitNotFound(msg = "No implicit view available from ${T1} => ${R}.") -trait Function1[@specialized(scala.Int, scala.Long, scala.Float, scala.Double/*, scala.AnyRef*/) -T1, @specialized(scala.Unit, scala.Boolean, scala.Int, scala.Float, scala.Long, scala.Double/*, scala.AnyRef*/) +R] extends AnyRef { self => +trait Function1[@specialized(scala.Int, scala.Long, scala.Float, scala.Double) -T1, @specialized(scala.Unit, scala.Boolean, scala.Int, scala.Float, scala.Long, scala.Double) +R] extends AnyRef { self => /** Apply the body of this function to the argument. * @return the result of function application. */ diff --git a/src/library/scala/Function10.scala b/src/library/scala/Function10.scala index f7e5d414f2..7789970a44 100644 --- a/src/library/scala/Function10.scala +++ b/src/library/scala/Function10.scala @@ -1,6 +1,6 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** +** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** diff --git a/src/library/scala/Function11.scala b/src/library/scala/Function11.scala index 53742bf733..d4276f3fd1 100644 --- a/src/library/scala/Function11.scala +++ b/src/library/scala/Function11.scala @@ -1,6 +1,6 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** +** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** diff --git a/src/library/scala/Function12.scala b/src/library/scala/Function12.scala index e349d9017d..dfa8bcfce6 100644 --- a/src/library/scala/Function12.scala +++ b/src/library/scala/Function12.scala @@ -1,6 +1,6 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** +** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** diff --git a/src/library/scala/Function13.scala b/src/library/scala/Function13.scala index 10ec64b87a..5404c208bf 100644 --- a/src/library/scala/Function13.scala +++ b/src/library/scala/Function13.scala @@ -1,6 +1,6 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** +** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** diff --git a/src/library/scala/Function14.scala b/src/library/scala/Function14.scala index 82dd409223..3145290bcf 100644 --- a/src/library/scala/Function14.scala +++ b/src/library/scala/Function14.scala @@ -1,6 +1,6 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** +** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** diff --git a/src/library/scala/Function15.scala b/src/library/scala/Function15.scala index be5fbeeca1..309ef53e71 100644 --- a/src/library/scala/Function15.scala +++ b/src/library/scala/Function15.scala @@ -1,6 +1,6 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** +** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** diff --git a/src/library/scala/Function16.scala b/src/library/scala/Function16.scala index 7a185b369c..c4cb107e87 100644 --- a/src/library/scala/Function16.scala +++ b/src/library/scala/Function16.scala @@ -1,6 +1,6 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** +** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** diff --git a/src/library/scala/Function17.scala b/src/library/scala/Function17.scala index 94e0000802..005ae2ab79 100644 --- a/src/library/scala/Function17.scala +++ b/src/library/scala/Function17.scala @@ -1,6 +1,6 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** +** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** diff --git a/src/library/scala/Function18.scala b/src/library/scala/Function18.scala index a3ee6776ba..371630dae3 100644 --- a/src/library/scala/Function18.scala +++ b/src/library/scala/Function18.scala @@ -1,6 +1,6 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** +** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** diff --git a/src/library/scala/Function19.scala b/src/library/scala/Function19.scala index 038dcbb778..95c60a467e 100644 --- a/src/library/scala/Function19.scala +++ b/src/library/scala/Function19.scala @@ -1,6 +1,6 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** +** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** diff --git a/src/library/scala/Function2.scala b/src/library/scala/Function2.scala index 0794a4048a..5690adb56a 100644 --- a/src/library/scala/Function2.scala +++ b/src/library/scala/Function2.scala @@ -1,6 +1,6 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** +** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** diff --git a/src/library/scala/Function20.scala b/src/library/scala/Function20.scala index 727684d6d5..a93f999d44 100644 --- a/src/library/scala/Function20.scala +++ b/src/library/scala/Function20.scala @@ -1,6 +1,6 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** +** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** diff --git a/src/library/scala/Function21.scala b/src/library/scala/Function21.scala index 2441278be8..7ebbb06798 100644 --- a/src/library/scala/Function21.scala +++ b/src/library/scala/Function21.scala @@ -1,6 +1,6 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** +** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** diff --git a/src/library/scala/Function22.scala b/src/library/scala/Function22.scala index 1f70b190a6..e5a3d83fb9 100644 --- a/src/library/scala/Function22.scala +++ b/src/library/scala/Function22.scala @@ -1,6 +1,6 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** +** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** diff --git a/src/library/scala/Function3.scala b/src/library/scala/Function3.scala index bbbde82056..850290d244 100644 --- a/src/library/scala/Function3.scala +++ b/src/library/scala/Function3.scala @@ -1,6 +1,6 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** +** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** diff --git a/src/library/scala/Function4.scala b/src/library/scala/Function4.scala index f100860a97..c9ac6df32e 100644 --- a/src/library/scala/Function4.scala +++ b/src/library/scala/Function4.scala @@ -1,6 +1,6 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** +** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** diff --git a/src/library/scala/Function5.scala b/src/library/scala/Function5.scala index cba9b6ce52..360a460306 100644 --- a/src/library/scala/Function5.scala +++ b/src/library/scala/Function5.scala @@ -1,6 +1,6 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** +** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** diff --git a/src/library/scala/Function6.scala b/src/library/scala/Function6.scala index 0b8addf7de..d30877e765 100644 --- a/src/library/scala/Function6.scala +++ b/src/library/scala/Function6.scala @@ -1,6 +1,6 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** +** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** diff --git a/src/library/scala/Function7.scala b/src/library/scala/Function7.scala index 2098658fa9..b19caf2b50 100644 --- a/src/library/scala/Function7.scala +++ b/src/library/scala/Function7.scala @@ -1,6 +1,6 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** +** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** diff --git a/src/library/scala/Function8.scala b/src/library/scala/Function8.scala index 08a480dce5..3aff0b034c 100644 --- a/src/library/scala/Function8.scala +++ b/src/library/scala/Function8.scala @@ -1,6 +1,6 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** +** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** diff --git a/src/library/scala/Function9.scala b/src/library/scala/Function9.scala index 2e35f7949c..f80ccf48f9 100644 --- a/src/library/scala/Function9.scala +++ b/src/library/scala/Function9.scala @@ -1,6 +1,6 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** +** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** diff --git a/src/library/scala/Int.scala b/src/library/scala/Int.scala index ae36413469..72e5ebf81b 100644 --- a/src/library/scala/Int.scala +++ b/src/library/scala/Int.scala @@ -1,17 +1,17 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** +** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** \* */ -// DO NOT EDIT, CHANGES WILL BE LOST. +// DO NOT EDIT, CHANGES WILL BE LOST +// This auto-generated code can be modified in scala.tools.cmd.gen. +// Afterwards, running tools/codegen-anyvals regenerates this source file. package scala -import scala.language.implicitConversions - /** `Int`, a 32-bit signed integer (equivalent to Java's `int` primitive type) is a * subtype of [[scala.AnyVal]]. Instances of `Int` are not * represented by an object in the underlying runtime system. @@ -37,13 +37,9 @@ final abstract class Int private extends AnyVal { * }}} */ def unary_~ : Int - /** - * Returns this value, unmodified. - */ + /** Returns this value, unmodified. */ def unary_+ : Int - /** - * Returns the negation of this value. - */ + /** Returns the negation of this value. */ def unary_- : Int def +(x: String): String @@ -105,178 +101,94 @@ final abstract class Int private extends AnyVal { */ def >>(x: Long): Int - /** - * Returns `true` if this value is equal to x, `false` otherwise. - */ + /** Returns `true` if this value is equal to x, `false` otherwise. */ def ==(x: Byte): Boolean - /** - * Returns `true` if this value is equal to x, `false` otherwise. - */ + /** Returns `true` if this value is equal to x, `false` otherwise. */ def ==(x: Short): Boolean - /** - * Returns `true` if this value is equal to x, `false` otherwise. - */ + /** Returns `true` if this value is equal to x, `false` otherwise. */ def ==(x: Char): Boolean - /** - * Returns `true` if this value is equal to x, `false` otherwise. - */ + /** Returns `true` if this value is equal to x, `false` otherwise. */ def ==(x: Int): Boolean - /** - * Returns `true` if this value is equal to x, `false` otherwise. - */ + /** Returns `true` if this value is equal to x, `false` otherwise. */ def ==(x: Long): Boolean - /** - * Returns `true` if this value is equal to x, `false` otherwise. - */ + /** Returns `true` if this value is equal to x, `false` otherwise. */ def ==(x: Float): Boolean - /** - * Returns `true` if this value is equal to x, `false` otherwise. - */ + /** Returns `true` if this value is equal to x, `false` otherwise. */ def ==(x: Double): Boolean - /** - * Returns `true` if this value is not equal to x, `false` otherwise. - */ + /** Returns `true` if this value is not equal to x, `false` otherwise. */ def !=(x: Byte): Boolean - /** - * Returns `true` if this value is not equal to x, `false` otherwise. - */ + /** Returns `true` if this value is not equal to x, `false` otherwise. */ def !=(x: Short): Boolean - /** - * Returns `true` if this value is not equal to x, `false` otherwise. - */ + /** Returns `true` if this value is not equal to x, `false` otherwise. */ def !=(x: Char): Boolean - /** - * Returns `true` if this value is not equal to x, `false` otherwise. - */ + /** Returns `true` if this value is not equal to x, `false` otherwise. */ def !=(x: Int): Boolean - /** - * Returns `true` if this value is not equal to x, `false` otherwise. - */ + /** Returns `true` if this value is not equal to x, `false` otherwise. */ def !=(x: Long): Boolean - /** - * Returns `true` if this value is not equal to x, `false` otherwise. - */ + /** Returns `true` if this value is not equal to x, `false` otherwise. */ def !=(x: Float): Boolean - /** - * Returns `true` if this value is not equal to x, `false` otherwise. - */ + /** Returns `true` if this value is not equal to x, `false` otherwise. */ def !=(x: Double): Boolean - /** - * Returns `true` if this value is less than x, `false` otherwise. - */ + /** Returns `true` if this value is less than x, `false` otherwise. */ def <(x: Byte): Boolean - /** - * Returns `true` if this value is less than x, `false` otherwise. - */ + /** Returns `true` if this value is less than x, `false` otherwise. */ def <(x: Short): Boolean - /** - * Returns `true` if this value is less than x, `false` otherwise. - */ + /** Returns `true` if this value is less than x, `false` otherwise. */ def <(x: Char): Boolean - /** - * Returns `true` if this value is less than x, `false` otherwise. - */ + /** Returns `true` if this value is less than x, `false` otherwise. */ def <(x: Int): Boolean - /** - * Returns `true` if this value is less than x, `false` otherwise. - */ + /** Returns `true` if this value is less than x, `false` otherwise. */ def <(x: Long): Boolean - /** - * Returns `true` if this value is less than x, `false` otherwise. - */ + /** Returns `true` if this value is less than x, `false` otherwise. */ def <(x: Float): Boolean - /** - * Returns `true` if this value is less than x, `false` otherwise. - */ + /** Returns `true` if this value is less than x, `false` otherwise. */ def <(x: Double): Boolean - /** - * Returns `true` if this value is less than or equal to x, `false` otherwise. - */ + /** Returns `true` if this value is less than or equal to x, `false` otherwise. */ def <=(x: Byte): Boolean - /** - * Returns `true` if this value is less than or equal to x, `false` otherwise. - */ + /** Returns `true` if this value is less than or equal to x, `false` otherwise. */ def <=(x: Short): Boolean - /** - * Returns `true` if this value is less than or equal to x, `false` otherwise. - */ + /** Returns `true` if this value is less than or equal to x, `false` otherwise. */ def <=(x: Char): Boolean - /** - * Returns `true` if this value is less than or equal to x, `false` otherwise. - */ + /** Returns `true` if this value is less than or equal to x, `false` otherwise. */ def <=(x: Int): Boolean - /** - * Returns `true` if this value is less than or equal to x, `false` otherwise. - */ + /** Returns `true` if this value is less than or equal to x, `false` otherwise. */ def <=(x: Long): Boolean - /** - * Returns `true` if this value is less than or equal to x, `false` otherwise. - */ + /** Returns `true` if this value is less than or equal to x, `false` otherwise. */ def <=(x: Float): Boolean - /** - * Returns `true` if this value is less than or equal to x, `false` otherwise. - */ + /** Returns `true` if this value is less than or equal to x, `false` otherwise. */ def <=(x: Double): Boolean - /** - * Returns `true` if this value is greater than x, `false` otherwise. - */ + /** Returns `true` if this value is greater than x, `false` otherwise. */ def >(x: Byte): Boolean - /** - * Returns `true` if this value is greater than x, `false` otherwise. - */ + /** Returns `true` if this value is greater than x, `false` otherwise. */ def >(x: Short): Boolean - /** - * Returns `true` if this value is greater than x, `false` otherwise. - */ + /** Returns `true` if this value is greater than x, `false` otherwise. */ def >(x: Char): Boolean - /** - * Returns `true` if this value is greater than x, `false` otherwise. - */ + /** Returns `true` if this value is greater than x, `false` otherwise. */ def >(x: Int): Boolean - /** - * Returns `true` if this value is greater than x, `false` otherwise. - */ + /** Returns `true` if this value is greater than x, `false` otherwise. */ def >(x: Long): Boolean - /** - * Returns `true` if this value is greater than x, `false` otherwise. - */ + /** Returns `true` if this value is greater than x, `false` otherwise. */ def >(x: Float): Boolean - /** - * Returns `true` if this value is greater than x, `false` otherwise. - */ + /** Returns `true` if this value is greater than x, `false` otherwise. */ def >(x: Double): Boolean - /** - * Returns `true` if this value is greater than or equal to x, `false` otherwise. - */ + /** Returns `true` if this value is greater than or equal to x, `false` otherwise. */ def >=(x: Byte): Boolean - /** - * Returns `true` if this value is greater than or equal to x, `false` otherwise. - */ + /** Returns `true` if this value is greater than or equal to x, `false` otherwise. */ def >=(x: Short): Boolean - /** - * Returns `true` if this value is greater than or equal to x, `false` otherwise. - */ + /** Returns `true` if this value is greater than or equal to x, `false` otherwise. */ def >=(x: Char): Boolean - /** - * Returns `true` if this value is greater than or equal to x, `false` otherwise. - */ + /** Returns `true` if this value is greater than or equal to x, `false` otherwise. */ def >=(x: Int): Boolean - /** - * Returns `true` if this value is greater than or equal to x, `false` otherwise. - */ + /** Returns `true` if this value is greater than or equal to x, `false` otherwise. */ def >=(x: Long): Boolean - /** - * Returns `true` if this value is greater than or equal to x, `false` otherwise. - */ + /** Returns `true` if this value is greater than or equal to x, `false` otherwise. */ def >=(x: Float): Boolean - /** - * Returns `true` if this value is greater than or equal to x, `false` otherwise. - */ + /** Returns `true` if this value is greater than or equal to x, `false` otherwise. */ def >=(x: Double): Boolean /** @@ -447,165 +359,95 @@ final abstract class Int private extends AnyVal { */ def ^(x: Long): Long - /** - * Returns the sum of this value and `x`. - */ + /** Returns the sum of this value and `x`. */ def +(x: Byte): Int - /** - * Returns the sum of this value and `x`. - */ + /** Returns the sum of this value and `x`. */ def +(x: Short): Int - /** - * Returns the sum of this value and `x`. - */ + /** Returns the sum of this value and `x`. */ def +(x: Char): Int - /** - * Returns the sum of this value and `x`. - */ + /** Returns the sum of this value and `x`. */ def +(x: Int): Int - /** - * Returns the sum of this value and `x`. - */ + /** Returns the sum of this value and `x`. */ def +(x: Long): Long - /** - * Returns the sum of this value and `x`. - */ + /** Returns the sum of this value and `x`. */ def +(x: Float): Float - /** - * Returns the sum of this value and `x`. - */ + /** Returns the sum of this value and `x`. */ def +(x: Double): Double - /** - * Returns the difference of this value and `x`. - */ + /** Returns the difference of this value and `x`. */ def -(x: Byte): Int - /** - * Returns the difference of this value and `x`. - */ + /** Returns the difference of this value and `x`. */ def -(x: Short): Int - /** - * Returns the difference of this value and `x`. - */ + /** Returns the difference of this value and `x`. */ def -(x: Char): Int - /** - * Returns the difference of this value and `x`. - */ + /** Returns the difference of this value and `x`. */ def -(x: Int): Int - /** - * Returns the difference of this value and `x`. - */ + /** Returns the difference of this value and `x`. */ def -(x: Long): Long - /** - * Returns the difference of this value and `x`. - */ + /** Returns the difference of this value and `x`. */ def -(x: Float): Float - /** - * Returns the difference of this value and `x`. - */ + /** Returns the difference of this value and `x`. */ def -(x: Double): Double - /** - * Returns the product of this value and `x`. - */ + /** Returns the product of this value and `x`. */ def *(x: Byte): Int - /** - * Returns the product of this value and `x`. - */ + /** Returns the product of this value and `x`. */ def *(x: Short): Int - /** - * Returns the product of this value and `x`. - */ + /** Returns the product of this value and `x`. */ def *(x: Char): Int - /** - * Returns the product of this value and `x`. - */ + /** Returns the product of this value and `x`. */ def *(x: Int): Int - /** - * Returns the product of this value and `x`. - */ + /** Returns the product of this value and `x`. */ def *(x: Long): Long - /** - * Returns the product of this value and `x`. - */ + /** Returns the product of this value and `x`. */ def *(x: Float): Float - /** - * Returns the product of this value and `x`. - */ + /** Returns the product of this value and `x`. */ def *(x: Double): Double - /** - * Returns the quotient of this value and `x`. - */ + /** Returns the quotient of this value and `x`. */ def /(x: Byte): Int - /** - * Returns the quotient of this value and `x`. - */ + /** Returns the quotient of this value and `x`. */ def /(x: Short): Int - /** - * Returns the quotient of this value and `x`. - */ + /** Returns the quotient of this value and `x`. */ def /(x: Char): Int - /** - * Returns the quotient of this value and `x`. - */ + /** Returns the quotient of this value and `x`. */ def /(x: Int): Int - /** - * Returns the quotient of this value and `x`. - */ + /** Returns the quotient of this value and `x`. */ def /(x: Long): Long - /** - * Returns the quotient of this value and `x`. - */ + /** Returns the quotient of this value and `x`. */ def /(x: Float): Float - /** - * Returns the quotient of this value and `x`. - */ + /** Returns the quotient of this value and `x`. */ def /(x: Double): Double - /** - * Returns the remainder of the division of this value by `x`. - */ + /** Returns the remainder of the division of this value by `x`. */ def %(x: Byte): Int - /** - * Returns the remainder of the division of this value by `x`. - */ + /** Returns the remainder of the division of this value by `x`. */ def %(x: Short): Int - /** - * Returns the remainder of the division of this value by `x`. - */ + /** Returns the remainder of the division of this value by `x`. */ def %(x: Char): Int - /** - * Returns the remainder of the division of this value by `x`. - */ + /** Returns the remainder of the division of this value by `x`. */ def %(x: Int): Int - /** - * Returns the remainder of the division of this value by `x`. - */ + /** Returns the remainder of the division of this value by `x`. */ def %(x: Long): Long - /** - * Returns the remainder of the division of this value by `x`. - */ + /** Returns the remainder of the division of this value by `x`. */ def %(x: Float): Float - /** - * Returns the remainder of the division of this value by `x`. - */ + /** Returns the remainder of the division of this value by `x`. */ def %(x: Double): Double override def getClass(): Class[Int] = null } object Int extends AnyValCompanion { - /** The smallest value representable as a Int. - */ + /** The smallest value representable as a Int. */ final val MinValue = java.lang.Integer.MIN_VALUE - /** The largest value representable as a Int. - */ + /** The largest value representable as a Int. */ final val MaxValue = java.lang.Integer.MAX_VALUE /** Transform a value type into a boxed reference type. * + * Runtime implementation determined by `scala.runtime.BoxesRunTime.boxToInteger`. See [[https://github.com/scala/scala src/library/scala/runtime/BoxesRunTime.java]]. + * * @param x the Int to be boxed * @return a java.lang.Integer offering `x` as its underlying value. */ @@ -615,18 +457,18 @@ object Int extends AnyValCompanion { * method is not typesafe: it accepts any Object, but will throw * an exception if the argument is not a java.lang.Integer. * + * Runtime implementation determined by `scala.runtime.BoxesRunTime.unboxToInt`. See [[https://github.com/scala/scala src/library/scala/runtime/BoxesRunTime.java]]. + * * @param x the java.lang.Integer to be unboxed. * @throws ClassCastException if the argument is not a java.lang.Integer * @return the Int resulting from calling intValue() on `x` */ def unbox(x: java.lang.Object): Int = x.asInstanceOf[java.lang.Integer].intValue() - /** The String representation of the scala.Int companion object. - */ + /** The String representation of the scala.Int companion object. */ override def toString = "object scala.Int" - - /** Language mandated coercions from Int to "wider" types. - */ + /** Language mandated coercions from Int to "wider" types. */ + import scala.language.implicitConversions implicit def int2long(x: Int): Long = x.toLong implicit def int2float(x: Int): Float = x.toFloat implicit def int2double(x: Int): Double = x.toDouble diff --git a/src/library/scala/Long.scala b/src/library/scala/Long.scala index 4ee9383c2a..1bd0fe88b1 100644 --- a/src/library/scala/Long.scala +++ b/src/library/scala/Long.scala @@ -1,17 +1,17 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** +** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** \* */ -// DO NOT EDIT, CHANGES WILL BE LOST. +// DO NOT EDIT, CHANGES WILL BE LOST +// This auto-generated code can be modified in scala.tools.cmd.gen. +// Afterwards, running tools/codegen-anyvals regenerates this source file. package scala -import scala.language.implicitConversions - /** `Long`, a 64-bit signed integer (equivalent to Java's `long` primitive type) is a * subtype of [[scala.AnyVal]]. Instances of `Long` are not * represented by an object in the underlying runtime system. @@ -37,13 +37,9 @@ final abstract class Long private extends AnyVal { * }}} */ def unary_~ : Long - /** - * Returns this value, unmodified. - */ + /** Returns this value, unmodified. */ def unary_+ : Long - /** - * Returns the negation of this value. - */ + /** Returns the negation of this value. */ def unary_- : Long def +(x: String): String @@ -105,178 +101,94 @@ final abstract class Long private extends AnyVal { */ def >>(x: Long): Long - /** - * Returns `true` if this value is equal to x, `false` otherwise. - */ + /** Returns `true` if this value is equal to x, `false` otherwise. */ def ==(x: Byte): Boolean - /** - * Returns `true` if this value is equal to x, `false` otherwise. - */ + /** Returns `true` if this value is equal to x, `false` otherwise. */ def ==(x: Short): Boolean - /** - * Returns `true` if this value is equal to x, `false` otherwise. - */ + /** Returns `true` if this value is equal to x, `false` otherwise. */ def ==(x: Char): Boolean - /** - * Returns `true` if this value is equal to x, `false` otherwise. - */ + /** Returns `true` if this value is equal to x, `false` otherwise. */ def ==(x: Int): Boolean - /** - * Returns `true` if this value is equal to x, `false` otherwise. - */ + /** Returns `true` if this value is equal to x, `false` otherwise. */ def ==(x: Long): Boolean - /** - * Returns `true` if this value is equal to x, `false` otherwise. - */ + /** Returns `true` if this value is equal to x, `false` otherwise. */ def ==(x: Float): Boolean - /** - * Returns `true` if this value is equal to x, `false` otherwise. - */ + /** Returns `true` if this value is equal to x, `false` otherwise. */ def ==(x: Double): Boolean - /** - * Returns `true` if this value is not equal to x, `false` otherwise. - */ + /** Returns `true` if this value is not equal to x, `false` otherwise. */ def !=(x: Byte): Boolean - /** - * Returns `true` if this value is not equal to x, `false` otherwise. - */ + /** Returns `true` if this value is not equal to x, `false` otherwise. */ def !=(x: Short): Boolean - /** - * Returns `true` if this value is not equal to x, `false` otherwise. - */ + /** Returns `true` if this value is not equal to x, `false` otherwise. */ def !=(x: Char): Boolean - /** - * Returns `true` if this value is not equal to x, `false` otherwise. - */ + /** Returns `true` if this value is not equal to x, `false` otherwise. */ def !=(x: Int): Boolean - /** - * Returns `true` if this value is not equal to x, `false` otherwise. - */ + /** Returns `true` if this value is not equal to x, `false` otherwise. */ def !=(x: Long): Boolean - /** - * Returns `true` if this value is not equal to x, `false` otherwise. - */ + /** Returns `true` if this value is not equal to x, `false` otherwise. */ def !=(x: Float): Boolean - /** - * Returns `true` if this value is not equal to x, `false` otherwise. - */ + /** Returns `true` if this value is not equal to x, `false` otherwise. */ def !=(x: Double): Boolean - /** - * Returns `true` if this value is less than x, `false` otherwise. - */ + /** Returns `true` if this value is less than x, `false` otherwise. */ def <(x: Byte): Boolean - /** - * Returns `true` if this value is less than x, `false` otherwise. - */ + /** Returns `true` if this value is less than x, `false` otherwise. */ def <(x: Short): Boolean - /** - * Returns `true` if this value is less than x, `false` otherwise. - */ + /** Returns `true` if this value is less than x, `false` otherwise. */ def <(x: Char): Boolean - /** - * Returns `true` if this value is less than x, `false` otherwise. - */ + /** Returns `true` if this value is less than x, `false` otherwise. */ def <(x: Int): Boolean - /** - * Returns `true` if this value is less than x, `false` otherwise. - */ + /** Returns `true` if this value is less than x, `false` otherwise. */ def <(x: Long): Boolean - /** - * Returns `true` if this value is less than x, `false` otherwise. - */ + /** Returns `true` if this value is less than x, `false` otherwise. */ def <(x: Float): Boolean - /** - * Returns `true` if this value is less than x, `false` otherwise. - */ + /** Returns `true` if this value is less than x, `false` otherwise. */ def <(x: Double): Boolean - /** - * Returns `true` if this value is less than or equal to x, `false` otherwise. - */ + /** Returns `true` if this value is less than or equal to x, `false` otherwise. */ def <=(x: Byte): Boolean - /** - * Returns `true` if this value is less than or equal to x, `false` otherwise. - */ + /** Returns `true` if this value is less than or equal to x, `false` otherwise. */ def <=(x: Short): Boolean - /** - * Returns `true` if this value is less than or equal to x, `false` otherwise. - */ + /** Returns `true` if this value is less than or equal to x, `false` otherwise. */ def <=(x: Char): Boolean - /** - * Returns `true` if this value is less than or equal to x, `false` otherwise. - */ + /** Returns `true` if this value is less than or equal to x, `false` otherwise. */ def <=(x: Int): Boolean - /** - * Returns `true` if this value is less than or equal to x, `false` otherwise. - */ + /** Returns `true` if this value is less than or equal to x, `false` otherwise. */ def <=(x: Long): Boolean - /** - * Returns `true` if this value is less than or equal to x, `false` otherwise. - */ + /** Returns `true` if this value is less than or equal to x, `false` otherwise. */ def <=(x: Float): Boolean - /** - * Returns `true` if this value is less than or equal to x, `false` otherwise. - */ + /** Returns `true` if this value is less than or equal to x, `false` otherwise. */ def <=(x: Double): Boolean - /** - * Returns `true` if this value is greater than x, `false` otherwise. - */ + /** Returns `true` if this value is greater than x, `false` otherwise. */ def >(x: Byte): Boolean - /** - * Returns `true` if this value is greater than x, `false` otherwise. - */ + /** Returns `true` if this value is greater than x, `false` otherwise. */ def >(x: Short): Boolean - /** - * Returns `true` if this value is greater than x, `false` otherwise. - */ + /** Returns `true` if this value is greater than x, `false` otherwise. */ def >(x: Char): Boolean - /** - * Returns `true` if this value is greater than x, `false` otherwise. - */ + /** Returns `true` if this value is greater than x, `false` otherwise. */ def >(x: Int): Boolean - /** - * Returns `true` if this value is greater than x, `false` otherwise. - */ + /** Returns `true` if this value is greater than x, `false` otherwise. */ def >(x: Long): Boolean - /** - * Returns `true` if this value is greater than x, `false` otherwise. - */ + /** Returns `true` if this value is greater than x, `false` otherwise. */ def >(x: Float): Boolean - /** - * Returns `true` if this value is greater than x, `false` otherwise. - */ + /** Returns `true` if this value is greater than x, `false` otherwise. */ def >(x: Double): Boolean - /** - * Returns `true` if this value is greater than or equal to x, `false` otherwise. - */ + /** Returns `true` if this value is greater than or equal to x, `false` otherwise. */ def >=(x: Byte): Boolean - /** - * Returns `true` if this value is greater than or equal to x, `false` otherwise. - */ + /** Returns `true` if this value is greater than or equal to x, `false` otherwise. */ def >=(x: Short): Boolean - /** - * Returns `true` if this value is greater than or equal to x, `false` otherwise. - */ + /** Returns `true` if this value is greater than or equal to x, `false` otherwise. */ def >=(x: Char): Boolean - /** - * Returns `true` if this value is greater than or equal to x, `false` otherwise. - */ + /** Returns `true` if this value is greater than or equal to x, `false` otherwise. */ def >=(x: Int): Boolean - /** - * Returns `true` if this value is greater than or equal to x, `false` otherwise. - */ + /** Returns `true` if this value is greater than or equal to x, `false` otherwise. */ def >=(x: Long): Boolean - /** - * Returns `true` if this value is greater than or equal to x, `false` otherwise. - */ + /** Returns `true` if this value is greater than or equal to x, `false` otherwise. */ def >=(x: Float): Boolean - /** - * Returns `true` if this value is greater than or equal to x, `false` otherwise. - */ + /** Returns `true` if this value is greater than or equal to x, `false` otherwise. */ def >=(x: Double): Boolean /** @@ -447,165 +359,95 @@ final abstract class Long private extends AnyVal { */ def ^(x: Long): Long - /** - * Returns the sum of this value and `x`. - */ + /** Returns the sum of this value and `x`. */ def +(x: Byte): Long - /** - * Returns the sum of this value and `x`. - */ + /** Returns the sum of this value and `x`. */ def +(x: Short): Long - /** - * Returns the sum of this value and `x`. - */ + /** Returns the sum of this value and `x`. */ def +(x: Char): Long - /** - * Returns the sum of this value and `x`. - */ + /** Returns the sum of this value and `x`. */ def +(x: Int): Long - /** - * Returns the sum of this value and `x`. - */ + /** Returns the sum of this value and `x`. */ def +(x: Long): Long - /** - * Returns the sum of this value and `x`. - */ + /** Returns the sum of this value and `x`. */ def +(x: Float): Float - /** - * Returns the sum of this value and `x`. - */ + /** Returns the sum of this value and `x`. */ def +(x: Double): Double - /** - * Returns the difference of this value and `x`. - */ + /** Returns the difference of this value and `x`. */ def -(x: Byte): Long - /** - * Returns the difference of this value and `x`. - */ + /** Returns the difference of this value and `x`. */ def -(x: Short): Long - /** - * Returns the difference of this value and `x`. - */ + /** Returns the difference of this value and `x`. */ def -(x: Char): Long - /** - * Returns the difference of this value and `x`. - */ + /** Returns the difference of this value and `x`. */ def -(x: Int): Long - /** - * Returns the difference of this value and `x`. - */ + /** Returns the difference of this value and `x`. */ def -(x: Long): Long - /** - * Returns the difference of this value and `x`. - */ + /** Returns the difference of this value and `x`. */ def -(x: Float): Float - /** - * Returns the difference of this value and `x`. - */ + /** Returns the difference of this value and `x`. */ def -(x: Double): Double - /** - * Returns the product of this value and `x`. - */ + /** Returns the product of this value and `x`. */ def *(x: Byte): Long - /** - * Returns the product of this value and `x`. - */ + /** Returns the product of this value and `x`. */ def *(x: Short): Long - /** - * Returns the product of this value and `x`. - */ + /** Returns the product of this value and `x`. */ def *(x: Char): Long - /** - * Returns the product of this value and `x`. - */ + /** Returns the product of this value and `x`. */ def *(x: Int): Long - /** - * Returns the product of this value and `x`. - */ + /** Returns the product of this value and `x`. */ def *(x: Long): Long - /** - * Returns the product of this value and `x`. - */ + /** Returns the product of this value and `x`. */ def *(x: Float): Float - /** - * Returns the product of this value and `x`. - */ + /** Returns the product of this value and `x`. */ def *(x: Double): Double - /** - * Returns the quotient of this value and `x`. - */ + /** Returns the quotient of this value and `x`. */ def /(x: Byte): Long - /** - * Returns the quotient of this value and `x`. - */ + /** Returns the quotient of this value and `x`. */ def /(x: Short): Long - /** - * Returns the quotient of this value and `x`. - */ + /** Returns the quotient of this value and `x`. */ def /(x: Char): Long - /** - * Returns the quotient of this value and `x`. - */ + /** Returns the quotient of this value and `x`. */ def /(x: Int): Long - /** - * Returns the quotient of this value and `x`. - */ + /** Returns the quotient of this value and `x`. */ def /(x: Long): Long - /** - * Returns the quotient of this value and `x`. - */ + /** Returns the quotient of this value and `x`. */ def /(x: Float): Float - /** - * Returns the quotient of this value and `x`. - */ + /** Returns the quotient of this value and `x`. */ def /(x: Double): Double - /** - * Returns the remainder of the division of this value by `x`. - */ + /** Returns the remainder of the division of this value by `x`. */ def %(x: Byte): Long - /** - * Returns the remainder of the division of this value by `x`. - */ + /** Returns the remainder of the division of this value by `x`. */ def %(x: Short): Long - /** - * Returns the remainder of the division of this value by `x`. - */ + /** Returns the remainder of the division of this value by `x`. */ def %(x: Char): Long - /** - * Returns the remainder of the division of this value by `x`. - */ + /** Returns the remainder of the division of this value by `x`. */ def %(x: Int): Long - /** - * Returns the remainder of the division of this value by `x`. - */ + /** Returns the remainder of the division of this value by `x`. */ def %(x: Long): Long - /** - * Returns the remainder of the division of this value by `x`. - */ + /** Returns the remainder of the division of this value by `x`. */ def %(x: Float): Float - /** - * Returns the remainder of the division of this value by `x`. - */ + /** Returns the remainder of the division of this value by `x`. */ def %(x: Double): Double override def getClass(): Class[Long] = null } object Long extends AnyValCompanion { - /** The smallest value representable as a Long. - */ + /** The smallest value representable as a Long. */ final val MinValue = java.lang.Long.MIN_VALUE - /** The largest value representable as a Long. - */ + /** The largest value representable as a Long. */ final val MaxValue = java.lang.Long.MAX_VALUE /** Transform a value type into a boxed reference type. * + * Runtime implementation determined by `scala.runtime.BoxesRunTime.boxToLong`. See [[https://github.com/scala/scala src/library/scala/runtime/BoxesRunTime.java]]. + * * @param x the Long to be boxed * @return a java.lang.Long offering `x` as its underlying value. */ @@ -615,18 +457,18 @@ object Long extends AnyValCompanion { * method is not typesafe: it accepts any Object, but will throw * an exception if the argument is not a java.lang.Long. * + * Runtime implementation determined by `scala.runtime.BoxesRunTime.unboxToLong`. See [[https://github.com/scala/scala src/library/scala/runtime/BoxesRunTime.java]]. + * * @param x the java.lang.Long to be unboxed. * @throws ClassCastException if the argument is not a java.lang.Long * @return the Long resulting from calling longValue() on `x` */ def unbox(x: java.lang.Object): Long = x.asInstanceOf[java.lang.Long].longValue() - /** The String representation of the scala.Long companion object. - */ + /** The String representation of the scala.Long companion object. */ override def toString = "object scala.Long" - - /** Language mandated coercions from Long to "wider" types. - */ + /** Language mandated coercions from Long to "wider" types. */ + import scala.language.implicitConversions implicit def long2float(x: Long): Float = x.toFloat implicit def long2double(x: Long): Double = x.toDouble } diff --git a/src/library/scala/LowPriorityImplicits.scala b/src/library/scala/LowPriorityImplicits.scala deleted file mode 100644 index bf6e494c11..0000000000 --- a/src/library/scala/LowPriorityImplicits.scala +++ /dev/null @@ -1,95 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala - -import scala.collection.{ mutable, immutable, generic } -import mutable.WrappedArray -import immutable.WrappedString -import generic.CanBuildFrom -import scala.language.implicitConversions - -/** The `LowPriorityImplicits` class provides implicit values that - * are valid in all Scala compilation units without explicit qualification, - * but that are partially overridden by higher-priority conversions in object - * `Predef`. - * - * @author Martin Odersky - * @since 2.8 - */ -class LowPriorityImplicits { - /** We prefer the java.lang.* boxed types to these wrappers in - * any potential conflicts. Conflicts do exist because the wrappers - * need to implement ScalaNumber in order to have a symmetric equals - * method, but that implies implementing java.lang.Number as well. - * - * Note - these are inlined because they are value classes, but - * the call to xxxWrapper is not eliminated even though it does nothing. - * Even inlined, every call site does a no-op retrieval of Predef's MODULE$ - * because maybe loading Predef has side effects! - */ - @inline implicit def byteWrapper(x: Byte) = new runtime.RichByte(x) - @inline implicit def shortWrapper(x: Short) = new runtime.RichShort(x) - @inline implicit def intWrapper(x: Int) = new runtime.RichInt(x) - @inline implicit def charWrapper(c: Char) = new runtime.RichChar(c) - @inline implicit def longWrapper(x: Long) = new runtime.RichLong(x) - @inline implicit def floatWrapper(x: Float) = new runtime.RichFloat(x) - @inline implicit def doubleWrapper(x: Double) = new runtime.RichDouble(x) - @inline implicit def booleanWrapper(x: Boolean) = new runtime.RichBoolean(x) - - // These eight implicits exist solely to exclude Null from the domain of - // the boxed types, so that e.g. "var x: Int = null" is a compile time - // error rather than a delayed null pointer exception by way of the - // conversion from java.lang.Integer. If defined in the same file as - // Integer2int, they would have higher priority because Null is a subtype - // of Integer. We balance that out and create conflict by moving the - // definition into the superclass. - // - // Caution: do not adjust tightrope tension without safety goggles in place. - implicit def Byte2byteNullConflict(x: Null): Byte = sys.error("value error") - implicit def Short2shortNullConflict(x: Null): Short = sys.error("value error") - implicit def Character2charNullConflict(x: Null): Char = sys.error("value error") - implicit def Integer2intNullConflict(x: Null): Int = sys.error("value error") - implicit def Long2longNullConflict(x: Null): Long = sys.error("value error") - implicit def Float2floatNullConflict(x: Null): Float = sys.error("value error") - implicit def Double2doubleNullConflict(x: Null): Double = sys.error("value error") - implicit def Boolean2booleanNullConflict(x: Null): Boolean = sys.error("value error") - - implicit def genericWrapArray[T](xs: Array[T]): WrappedArray[T] = - if (xs eq null) null - else WrappedArray.make(xs) - - // Since the JVM thinks arrays are covariant, one 0-length Array[AnyRef] - // is as good as another for all T <: AnyRef. Instead of creating 100,000,000 - // unique ones by way of this implicit, let's share one. - implicit def wrapRefArray[T <: AnyRef](xs: Array[T]): WrappedArray[T] = { - if (xs eq null) null - else if (xs.length == 0) WrappedArray.empty[T] - else new WrappedArray.ofRef[T](xs) - } - - implicit def wrapIntArray(xs: Array[Int]): WrappedArray[Int] = if (xs ne null) new WrappedArray.ofInt(xs) else null - implicit def wrapDoubleArray(xs: Array[Double]): WrappedArray[Double] = if (xs ne null) new WrappedArray.ofDouble(xs) else null - implicit def wrapLongArray(xs: Array[Long]): WrappedArray[Long] = if (xs ne null) new WrappedArray.ofLong(xs) else null - implicit def wrapFloatArray(xs: Array[Float]): WrappedArray[Float] = if (xs ne null) new WrappedArray.ofFloat(xs) else null - implicit def wrapCharArray(xs: Array[Char]): WrappedArray[Char] = if (xs ne null) new WrappedArray.ofChar(xs) else null - implicit def wrapByteArray(xs: Array[Byte]): WrappedArray[Byte] = if (xs ne null) new WrappedArray.ofByte(xs) else null - implicit def wrapShortArray(xs: Array[Short]): WrappedArray[Short] = if (xs ne null) new WrappedArray.ofShort(xs) else null - implicit def wrapBooleanArray(xs: Array[Boolean]): WrappedArray[Boolean] = if (xs ne null) new WrappedArray.ofBoolean(xs) else null - implicit def wrapUnitArray(xs: Array[Unit]): WrappedArray[Unit] = if (xs ne null) new WrappedArray.ofUnit(xs) else null - - implicit def wrapString(s: String): WrappedString = if (s ne null) new WrappedString(s) else null - implicit def unwrapString(ws: WrappedString): String = if (ws ne null) ws.self else null - - implicit def fallbackStringCanBuildFrom[T]: CanBuildFrom[String, T, immutable.IndexedSeq[T]] = - new CanBuildFrom[String, T, immutable.IndexedSeq[T]] { - def apply(from: String) = immutable.IndexedSeq.newBuilder[T] - def apply() = immutable.IndexedSeq.newBuilder[T] - } -} - diff --git a/src/library/scala/NotNull.scala b/src/library/scala/NotNull.scala index f87416b49d..3cbe9ed4ac 100644 --- a/src/library/scala/NotNull.scala +++ b/src/library/scala/NotNull.scala @@ -12,4 +12,6 @@ package scala * A marker trait for things that are not allowed to be null * @since 2.5 */ + +@deprecated("This trait will be removed", "2.11.0") trait NotNull extends Any {} diff --git a/src/library/scala/Option.scala b/src/library/scala/Option.scala index 3873df99e9..905e925f57 100644 --- a/src/library/scala/Option.scala +++ b/src/library/scala/Option.scala @@ -128,7 +128,7 @@ sealed abstract class Option[+A] extends Product with Serializable { * val textField = new JComponent(initalText.orNull,20) * }}} */ - @inline final def orNull[A1 >: A](implicit ev: Null <:< A1): A1 = this getOrElse null + @inline final def orNull[A1 >: A](implicit ev: Null <:< A1): A1 = this getOrElse ev(null) /** Returns a $some containing the result of applying $f to this $option's * value if this $option is nonempty. @@ -209,6 +209,15 @@ sealed abstract class Option[+A] extends Product with Serializable { def withFilter(q: A => Boolean): WithFilter = new WithFilter(x => p(x) && q(x)) } + /** Tests whether the option contains a given value as an element. + * + * @param elem the element to test. + * @return `true` if the option has an element that is equal (as + * determined by `==`) to `elem`, `false` otherwise. + */ + final def contains[A1 >: A](elem: A1): Boolean = + !isEmpty && this.get == elem + /** Returns true if this option is nonempty '''and''' the predicate * $p returns true when applied to this $option's value. * Otherwise, returns false. @@ -247,7 +256,7 @@ sealed abstract class Option[+A] extends Product with Serializable { * value (if possible), or $none. */ @inline final def collect[B](pf: PartialFunction[A, B]): Option[B] = - if (!isEmpty && pf.isDefinedAt(this.get)) Some(pf(this.get)) else None + if (!isEmpty) pf.lift(this.get) else None /** Returns this $option if it is nonempty, * otherwise return the result of evaluating `alternative`. diff --git a/src/library/scala/PartialFunction.scala b/src/library/scala/PartialFunction.scala index 9ff648a05a..7f4a9dc45d 100644 --- a/src/library/scala/PartialFunction.scala +++ b/src/library/scala/PartialFunction.scala @@ -94,7 +94,7 @@ trait PartialFunction[-A, +B] extends (A => B) { self => * Note that expression `pf.applyOrElse(x, default)` is equivalent to * {{{ if(pf isDefinedAt x) pf(x) else default(x) }}} * except that `applyOrElse` method can be implemented more efficiently. - * For all partial function literals compiler generates `applyOrElse` implementation which + * For all partial function literals the compiler generates an `applyOrElse` implementation which * avoids double evaluation of pattern matchers and guards. * This makes `applyOrElse` the basis for the efficient implementation for many operations and scenarios, such as: * diff --git a/src/library/scala/Predef.scala b/src/library/scala/Predef.scala index 9bb57877d9..faeb1dcbe2 100644 --- a/src/library/scala/Predef.scala +++ b/src/library/scala/Predef.scala @@ -15,6 +15,7 @@ import generic.CanBuildFrom import scala.annotation.{ elidable, implicitNotFound } import scala.annotation.elidable.ASSERTION import scala.language.{implicitConversions, existentials} +import scala.io.StdIn /** The `Predef` object provides definitions that are accessible in all Scala * compilation units without explicit qualification. @@ -25,8 +26,6 @@ import scala.language.{implicitConversions, existentials} * [[scala.collection.immutable.Set]], and the [[scala.collection.immutable.List]] * constructors ([[scala.collection.immutable.::]] and * [[scala.collection.immutable.Nil]]). - * The types `Pair` (a [[scala.Tuple2]]) and `Triple` (a [[scala.Tuple3]]), with - * simple constructors, are also provided. * * === Console I/O === * Predef provides a number of simple functions for console I/O, such as @@ -68,7 +67,7 @@ import scala.language.{implicitConversions, existentials} * Short value to a Long value as required, and to add additional higher-order * functions to Array values. These are described in more detail in the documentation of [[scala.Array]]. */ -object Predef extends LowPriorityImplicits { +object Predef extends LowPriorityImplicits with DeprecatedPredef { /** * Retrieve the runtime representation of a class type. `classOf[T]` is equivalent to * the class literal `T.class` in Java. @@ -96,24 +95,22 @@ object Predef extends LowPriorityImplicits { type Set[A] = immutable.Set[A] val Map = immutable.Map val Set = immutable.Set - // @deprecated("Use scala.AnyRef instead", "2.10.0") - // def AnyRef = scala.AnyRef // Manifest types, companions, and incantations for summoning @annotation.implicitNotFound(msg = "No ClassManifest available for ${T}.") - @deprecated("Use scala.reflect.ClassTag instead", "2.10.0") + @deprecated("Use `scala.reflect.ClassTag` instead", "2.10.0") type ClassManifest[T] = scala.reflect.ClassManifest[T] // TODO undeprecated until Scala reflection becomes non-experimental // @deprecated("This notion doesn't have a corresponding concept in 2.10, because scala.reflect.runtime.universe.TypeTag can capture arbitrary types. Use type tags instead of manifests, and there will be no need in opt manifests.", "2.10.0") type OptManifest[T] = scala.reflect.OptManifest[T] @annotation.implicitNotFound(msg = "No Manifest available for ${T}.") // TODO undeprecated until Scala reflection becomes non-experimental - // @deprecated("Use scala.reflect.ClassTag (to capture erasures) or scala.reflect.runtime.universe.TypeTag (to capture types) or both instead", "2.10.0") + // @deprecated("Use `scala.reflect.ClassTag` (to capture erasures) or scala.reflect.runtime.universe.TypeTag (to capture types) or both instead", "2.10.0") type Manifest[T] = scala.reflect.Manifest[T] - @deprecated("Use scala.reflect.ClassTag instead", "2.10.0") + @deprecated("Use `scala.reflect.ClassTag` instead", "2.10.0") val ClassManifest = scala.reflect.ClassManifest // TODO undeprecated until Scala reflection becomes non-experimental - // @deprecated("Use scala.reflect.ClassTag (to capture erasures) or scala.reflect.runtime.universe.TypeTag (to capture types) or both instead", "2.10.0") + // @deprecated("Use `scala.reflect.ClassTag` (to capture erasures) or scala.reflect.runtime.universe.TypeTag (to capture types) or both instead", "2.10.0") val Manifest = scala.reflect.Manifest // TODO undeprecated until Scala reflection becomes non-experimental // @deprecated("This notion doesn't have a corresponding concept in 2.10, because scala.reflect.runtime.universe.TypeTag can capture arbitrary types. Use type tags instead of manifests, and there will be no need in opt manifests.", "2.10.0") @@ -133,25 +130,14 @@ object Predef extends LowPriorityImplicits { @inline def implicitly[T](implicit e: T) = e // for summoning implicit values from the nether world -- TODO: when dependent method types are on by default, give this result type `e.type`, so that inliner has better chance of knowing which method to inline in calls like `implicitly[MatchingStrategy[Option]].zero` @inline def locally[T](x: T): T = x // to communicate intent and avoid unmoored statements - // Apparently needed for the xml library - val $scope = scala.xml.TopScope - - // Deprecated + // errors and asserts ------------------------------------------------- + // !!! Remove this when possible - ideally for 2.11. + // We are stuck with it a while longer because sbt's compiler interface + // still calls it as of 0.12.2. @deprecated("Use `sys.error(message)` instead", "2.9.0") def error(message: String): Nothing = sys.error(message) - @deprecated("Use `sys.exit()` instead", "2.9.0") - def exit(): Nothing = sys.exit() - - @deprecated("Use `sys.exit(status)` instead", "2.9.0") - def exit(status: Int): Nothing = sys.exit(status) - - @deprecated("Use `formatString.format(args: _*)` or `arg.formatted(formatString)` instead", "2.9.0") - def format(text: String, xs: Any*) = augmentString(text).format(xs: _*) - - // errors and asserts ------------------------------------------------- - /** Tests an expression, throwing an `AssertionError` if false. * Calls to this method will not be generated if `-Xelide-below` * is at least `ASSERTION`. @@ -233,19 +219,6 @@ object Predef extends LowPriorityImplicits { throw new IllegalArgumentException("requirement failed: "+ message) } - final class Ensuring[A](val __resultOfEnsuring: A) extends AnyVal { - // `__resultOfEnsuring` must be a public val to allow inlining. - // See comments in ArrowAssoc for more. - @deprecated("Use `__resultOfEnsuring` instead", "2.10.0") - def x = __resultOfEnsuring - - def ensuring(cond: Boolean): A = { assert(cond); __resultOfEnsuring } - def ensuring(cond: Boolean, msg: => Any): A = { assert(cond, msg); __resultOfEnsuring } - def ensuring(cond: A => Boolean): A = { assert(cond(__resultOfEnsuring)); __resultOfEnsuring } - def ensuring(cond: A => Boolean, msg: => Any): A = { assert(cond(__resultOfEnsuring), msg); __resultOfEnsuring } - } - @inline implicit def any2Ensuring[A](x: A): Ensuring[A] = new Ensuring(x) - /** `???` can be used for marking methods that remain to be implemented. * @throws A `NotImplementedError` */ @@ -253,32 +226,82 @@ object Predef extends LowPriorityImplicits { // tupling ------------------------------------------------------------ + @deprecated("Use built-in tuple syntax or Tuple2 instead", "2.11.0") type Pair[+A, +B] = Tuple2[A, B] + @deprecated("Use built-in tuple syntax or Tuple2 instead", "2.11.0") object Pair { def apply[A, B](x: A, y: B) = Tuple2(x, y) def unapply[A, B](x: Tuple2[A, B]): Option[Tuple2[A, B]] = Some(x) } + @deprecated("Use built-in tuple syntax or Tuple3 instead", "2.11.0") type Triple[+A, +B, +C] = Tuple3[A, B, C] + @deprecated("Use built-in tuple syntax or Tuple3 instead", "2.11.0") object Triple { def apply[A, B, C](x: A, y: B, z: C) = Tuple3(x, y, z) def unapply[A, B, C](x: Tuple3[A, B, C]): Option[Tuple3[A, B, C]] = Some(x) } - final class ArrowAssoc[A](val __leftOfArrow: A) extends AnyVal { - // `__leftOfArrow` must be a public val to allow inlining. The val - // used to be called `x`, but now goes by `__leftOfArrow`, as that - // reduces the chances of a user's writing `foo.__leftOfArrow` and - // being confused why they get an ambiguous implicit conversion - // error. (`foo.x` used to produce this error since both - // any2Ensuring and any2ArrowAssoc pimped an `x` onto everything) - @deprecated("Use `__leftOfArrow` instead", "2.10.0") - def x = __leftOfArrow - - @inline def -> [B](y: B): Tuple2[A, B] = Tuple2(__leftOfArrow, y) + // implicit classes ----------------------------------------------------- + + implicit final class ArrowAssoc[A](private val self: A) extends AnyVal { + @inline def -> [B](y: B): Tuple2[A, B] = Tuple2(self, y) def →[B](y: B): Tuple2[A, B] = ->(y) } - @inline implicit def any2ArrowAssoc[A](x: A): ArrowAssoc[A] = new ArrowAssoc(x) + + implicit final class Ensuring[A](private val self: A) extends AnyVal { + def ensuring(cond: Boolean): A = { assert(cond); self } + def ensuring(cond: Boolean, msg: => Any): A = { assert(cond, msg); self } + def ensuring(cond: A => Boolean): A = { assert(cond(self)); self } + def ensuring(cond: A => Boolean, msg: => Any): A = { assert(cond(self), msg); self } + } + + implicit final class StringFormat[A](private val self: A) extends AnyVal { + /** Returns string formatted according to given `format` string. + * Format strings are as for `String.format` + * (@see java.lang.String.format). + */ + @inline def formatted(fmtstr: String): String = fmtstr format self + } + + // TODO: remove, only needed for binary compatibility of 2.11.0-RC1 with 2.11.0-M8 + // note that `private[scala]` becomes `public` in bytecode + private[scala] final class StringAdd[A](private val self: A) extends AnyVal { + def +(other: String): String = String.valueOf(self) + other + } + private[scala] def StringAdd(x: Any): Any = new StringAdd(x) + + // SI-8229 retaining the pre 2.11 name for source compatibility in shadowing this implicit + implicit final class any2stringadd[A](private val self: A) extends AnyVal { + def +(other: String): String = String.valueOf(self) + other + } + + implicit final class RichException(private val self: Throwable) extends AnyVal { + import scala.compat.Platform.EOL + @deprecated("Use Throwable#getStackTrace", "2.11.0") def getStackTraceString = self.getStackTrace().mkString("", EOL, EOL) + } + + implicit final class SeqCharSequence(val __sequenceOfChars: scala.collection.IndexedSeq[Char]) extends CharSequence { + def length: Int = __sequenceOfChars.length + def charAt(index: Int): Char = __sequenceOfChars(index) + def subSequence(start: Int, end: Int): CharSequence = new SeqCharSequence(__sequenceOfChars.slice(start, end)) + override def toString = __sequenceOfChars mkString "" + } + + implicit final class ArrayCharSequence(val __arrayOfChars: Array[Char]) extends CharSequence { + def length: Int = __arrayOfChars.length + def charAt(index: Int): Char = __arrayOfChars(index) + def subSequence(start: Int, end: Int): CharSequence = new runtime.ArrayCharSequence(__arrayOfChars, start, end) + override def toString = __arrayOfChars mkString "" + } + + implicit val StringCanBuildFrom: CanBuildFrom[String, Char, String] = new CanBuildFrom[String, Char, String] { + def apply(from: String) = apply() + def apply() = mutable.StringBuilder.newBuilder + } + + @inline implicit def augmentString(x: String): StringOps = new StringOps(x) + @inline implicit def unaugmentString(x: StringOps): String = x.repr // printing and reading ----------------------------------------------- @@ -287,28 +310,10 @@ object Predef extends LowPriorityImplicits { def println(x: Any) = Console.println(x) def printf(text: String, xs: Any*) = Console.print(text.format(xs: _*)) - def readLine(): String = Console.readLine() - def readLine(text: String, args: Any*) = Console.readLine(text, args: _*) - def readBoolean() = Console.readBoolean() - def readByte() = Console.readByte() - def readShort() = Console.readShort() - def readChar() = Console.readChar() - def readInt() = Console.readInt() - def readLong() = Console.readLong() - def readFloat() = Console.readFloat() - def readDouble() = Console.readDouble() - def readf(format: String) = Console.readf(format) - def readf1(format: String) = Console.readf1(format) - def readf2(format: String) = Console.readf2(format) - def readf3(format: String) = Console.readf3(format) - // views -------------------------------------------------------------- - implicit def exceptionWrapper(exc: Throwable) = new runtime.RichException(exc) implicit def tuple2ToZippedOps[T1, T2](x: (T1, T2)) = new runtime.Tuple2Zipped.Ops(x) implicit def tuple3ToZippedOps[T1, T2, T3](x: (T1, T2, T3)) = new runtime.Tuple3Zipped.Ops(x) - implicit def seqToCharSequence(xs: scala.collection.IndexedSeq[Char]): CharSequence = new runtime.SeqCharSequence(xs) - implicit def arrayToCharSequence(xs: Array[Char]): CharSequence = new runtime.ArrayCharSequence(xs, 0, xs.length) implicit def genericArrayOps[T](xs: Array[T]): ArrayOps[T] = (xs match { case x: Array[AnyRef] => refArrayOps[AnyRef](x) @@ -335,33 +340,6 @@ object Predef extends LowPriorityImplicits { implicit def shortArrayOps(xs: Array[Short]): ArrayOps[Short] = new ArrayOps.ofShort(xs) implicit def unitArrayOps(xs: Array[Unit]): ArrayOps[Unit] = new ArrayOps.ofUnit(xs) - // Primitive Widenings -------------------------------------------------------------- - - @deprecated("Use `.toShort` for explicit conversion and `Byte.byte2short` for implicit conversion", "2.10.0") def byte2short(x: Byte): Short = x.toShort - @deprecated("Use `.toInt` for explicit conversion and `Byte.byte2int` for implicit conversion", "2.10.0") def byte2int(x: Byte): Int = x.toInt - @deprecated("Use `.toLong` for explicit conversion and `Byte.byte2long for implicit conversion", "2.10.0") def byte2long(x: Byte): Long = x.toLong - @deprecated("Use `.toFloat` for explicit conversion and `Byte.byte2float` for implicit conversion", "2.10.0") def byte2float(x: Byte): Float = x.toFloat - @deprecated("Use `.toDouble` for explicit conversion and `Byte.byte2double` for implicit conversion", "2.10.0") def byte2double(x: Byte): Double = x.toDouble - - @deprecated("Use `.toInt` for explicit conversion and `Short.short2int` for implicit conversion", "2.10.0") def short2int(x: Short): Int = x.toInt - @deprecated("Use `.toLong` for explicit conversion and `Short.short2long` for implicit conversion", "2.10.0") def short2long(x: Short): Long = x.toLong - @deprecated("Use `.toFloat` for explicit conversion and `Short.short2float` for implicit conversion", "2.10.0") def short2float(x: Short): Float = x.toFloat - @deprecated("Use `.toDouble` for explicit conversion and `Short.short2double` for implicit conversion", "2.10.0") def short2double(x: Short): Double = x.toDouble - - @deprecated("Use `.toInt` for explicit conversion and `Char.char2int` for implicit conversion", "2.10.0") def char2int(x: Char): Int = x.toInt - @deprecated("Use `.toLong` for explicit conversion and `Char.char2long` for implicit conversion", "2.10.0") def char2long(x: Char): Long = x.toLong - @deprecated("Use `.toFloat` for explicit conversion and `Char.char2float` for implicit conversion", "2.10.0") def char2float(x: Char): Float = x.toFloat - @deprecated("Use `.toDouble` for explicit conversion and `Char.char2double` for implicit conversion", "2.10.0") def char2double(x: Char): Double = x.toDouble - - @deprecated("Use `.toLong` for explicit conversion and `Int.int2long` for implicit conversion", "2.10.0") def int2long(x: Int): Long = x.toLong - @deprecated("Use `.toFloat` for explicit conversion and `Int.int2float` for implicit conversion", "2.10.0") def int2float(x: Int): Float = x.toFloat - @deprecated("Use `.toDouble` for explicit conversion and `Int.int2double` for implicit conversion", "2.10.0") def int2double(x: Int): Double = x.toDouble - - @deprecated("Use `.toFloat` for explicit conversion and `Long.long2float` for implicit conversion", "2.10.0") def long2float(x: Long): Float = x.toFloat - @deprecated("Use `.toDouble` for explicit conversion and `Long.long2double` for implicit conversion", "2.10.0") def long2double(x: Long): Double = x.toDouble - - @deprecated("Use `.toDouble` for explicit conversion and `Float.float2double` for implicit conversion", "2.10.0") def float2double(x: Float): Double = x.toDouble - // "Autoboxing" and "Autounboxing" --------------------------------------------------- implicit def byte2Byte(x: Byte) = java.lang.Byte.valueOf(x) @@ -373,19 +351,6 @@ object Predef extends LowPriorityImplicits { implicit def double2Double(x: Double) = java.lang.Double.valueOf(x) implicit def boolean2Boolean(x: Boolean) = java.lang.Boolean.valueOf(x) - // These next eight implicits exist solely to exclude AnyRef methods from the - // eight implicits above so that primitives are not coerced to AnyRefs. They - // only create such conflict for AnyRef methods, so the methods on the java.lang - // boxed types are unambiguously reachable. - implicit def byte2ByteConflict(x: Byte) = new AnyRef - implicit def short2ShortConflict(x: Short) = new AnyRef - implicit def char2CharacterConflict(x: Char) = new AnyRef - implicit def int2IntegerConflict(x: Int) = new AnyRef - implicit def long2LongConflict(x: Long) = new AnyRef - implicit def float2FloatConflict(x: Float) = new AnyRef - implicit def double2DoubleConflict(x: Double) = new AnyRef - implicit def boolean2BooleanConflict(x: Boolean) = new AnyRef - implicit def Byte2byte(x: java.lang.Byte): Byte = x.byteValue implicit def Short2short(x: java.lang.Short): Short = x.shortValue implicit def Character2char(x: java.lang.Character): Char = x.charValue @@ -395,21 +360,6 @@ object Predef extends LowPriorityImplicits { implicit def Double2double(x: java.lang.Double): Double = x.doubleValue implicit def Boolean2boolean(x: java.lang.Boolean): Boolean = x.booleanValue - // Strings and CharSequences -------------------------------------------------------------- - - @inline implicit def any2stringfmt(x: Any) = new runtime.StringFormat(x) - @inline implicit def augmentString(x: String): StringOps = new StringOps(x) - implicit def any2stringadd(x: Any) = new runtime.StringAdd(x) - implicit def unaugmentString(x: StringOps): String = x.repr - - @deprecated("Use `StringCanBuildFrom`", "2.10.0") - def stringCanBuildFrom: CanBuildFrom[String, Char, String] = StringCanBuildFrom - - implicit val StringCanBuildFrom: CanBuildFrom[String, Char, String] = new CanBuildFrom[String, Char, String] { - def apply(from: String) = apply() - def apply() = mutable.StringBuilder.newBuilder - } - // Type Constraints -------------------------------------------------------------- /** @@ -432,9 +382,13 @@ object Predef extends LowPriorityImplicits { @implicitNotFound(msg = "Cannot prove that ${From} <:< ${To}.") sealed abstract class <:<[-From, +To] extends (From => To) with Serializable private[this] final val singleton_<:< = new <:<[Any,Any] { def apply(x: Any): Any = x } - // not in the <:< companion object because it is also - // intended to subsume identity (which is no longer implicit) - implicit def conforms[A]: A <:< A = singleton_<:<.asInstanceOf[A <:< A] + // The dollar prefix is to dodge accidental shadowing of this method + // by a user-defined method of the same name (SI-7788). + // The collections rely on this method. + implicit def $conforms[A]: A <:< A = singleton_<:<.asInstanceOf[A <:< A] + + @deprecated("Use `implicitly[T <:< U]` or `identity` instead.", "2.11.0") + def conforms[A]: A <:< A = $conforms[A] /** An instance of `A =:= B` witnesses that the types `A` and `B` are equal. * @@ -460,3 +414,97 @@ object Predef extends LowPriorityImplicits { implicit def dummyImplicit: DummyImplicit = new DummyImplicit } } + +private[scala] trait DeprecatedPredef { + self: Predef.type => + + // Deprecated stubs for any who may have been calling these methods directly. + @deprecated("Use `ArrowAssoc`", "2.11.0") def any2ArrowAssoc[A](x: A): ArrowAssoc[A] = new ArrowAssoc(x) + @deprecated("Use `Ensuring`", "2.11.0") def any2Ensuring[A](x: A): Ensuring[A] = new Ensuring(x) + @deprecated("Use `StringFormat`", "2.11.0") def any2stringfmt(x: Any): StringFormat[Any] = new StringFormat(x) + @deprecated("Use `Throwable` directly", "2.11.0") def exceptionWrapper(exc: Throwable) = new RichException(exc) + @deprecated("Use `SeqCharSequence`", "2.11.0") def seqToCharSequence(xs: scala.collection.IndexedSeq[Char]): CharSequence = new SeqCharSequence(xs) + @deprecated("Use `ArrayCharSequence`", "2.11.0") def arrayToCharSequence(xs: Array[Char]): CharSequence = new ArrayCharSequence(xs) + + @deprecated("Use the method in `scala.io.StdIn`", "2.11.0") def readLine(): String = StdIn.readLine() + @deprecated("Use the method in `scala.io.StdIn`", "2.11.0") def readLine(text: String, args: Any*) = StdIn.readLine(text, args: _*) + @deprecated("Use the method in `scala.io.StdIn`", "2.11.0") def readBoolean() = StdIn.readBoolean() + @deprecated("Use the method in `scala.io.StdIn`", "2.11.0") def readByte() = StdIn.readByte() + @deprecated("Use the method in `scala.io.StdIn`", "2.11.0") def readShort() = StdIn.readShort() + @deprecated("Use the method in `scala.io.StdIn`", "2.11.0") def readChar() = StdIn.readChar() + @deprecated("Use the method in `scala.io.StdIn`", "2.11.0") def readInt() = StdIn.readInt() + @deprecated("Use the method in `scala.io.StdIn`", "2.11.0") def readLong() = StdIn.readLong() + @deprecated("Use the method in `scala.io.StdIn`", "2.11.0") def readFloat() = StdIn.readFloat() + @deprecated("Use the method in `scala.io.StdIn`", "2.11.0") def readDouble() = StdIn.readDouble() + @deprecated("Use the method in `scala.io.StdIn`", "2.11.0") def readf(format: String) = StdIn.readf(format) + @deprecated("Use the method in `scala.io.StdIn`", "2.11.0") def readf1(format: String) = StdIn.readf1(format) + @deprecated("Use the method in `scala.io.StdIn`", "2.11.0") def readf2(format: String) = StdIn.readf2(format) + @deprecated("Use the method in `scala.io.StdIn`", "2.11.0") def readf3(format: String) = StdIn.readf3(format) +} + +/** The `LowPriorityImplicits` class provides implicit values that +* are valid in all Scala compilation units without explicit qualification, +* but that are partially overridden by higher-priority conversions in object +* `Predef`. +* +* @author Martin Odersky +* @since 2.8 +*/ +// SI-7335 Parents of Predef are defined in the same compilation unit to avoid +// cyclic reference errors compiling the standard library *without* a previously +// compiled copy on the classpath. +private[scala] abstract class LowPriorityImplicits { + import mutable.WrappedArray + import immutable.WrappedString + + /** We prefer the java.lang.* boxed types to these wrappers in + * any potential conflicts. Conflicts do exist because the wrappers + * need to implement ScalaNumber in order to have a symmetric equals + * method, but that implies implementing java.lang.Number as well. + * + * Note - these are inlined because they are value classes, but + * the call to xxxWrapper is not eliminated even though it does nothing. + * Even inlined, every call site does a no-op retrieval of Predef's MODULE$ + * because maybe loading Predef has side effects! + */ + @inline implicit def byteWrapper(x: Byte) = new runtime.RichByte(x) + @inline implicit def shortWrapper(x: Short) = new runtime.RichShort(x) + @inline implicit def intWrapper(x: Int) = new runtime.RichInt(x) + @inline implicit def charWrapper(c: Char) = new runtime.RichChar(c) + @inline implicit def longWrapper(x: Long) = new runtime.RichLong(x) + @inline implicit def floatWrapper(x: Float) = new runtime.RichFloat(x) + @inline implicit def doubleWrapper(x: Double) = new runtime.RichDouble(x) + @inline implicit def booleanWrapper(x: Boolean) = new runtime.RichBoolean(x) + + implicit def genericWrapArray[T](xs: Array[T]): WrappedArray[T] = + if (xs eq null) null + else WrappedArray.make(xs) + + // Since the JVM thinks arrays are covariant, one 0-length Array[AnyRef] + // is as good as another for all T <: AnyRef. Instead of creating 100,000,000 + // unique ones by way of this implicit, let's share one. + implicit def wrapRefArray[T <: AnyRef](xs: Array[T]): WrappedArray[T] = { + if (xs eq null) null + else if (xs.length == 0) WrappedArray.empty[T] + else new WrappedArray.ofRef[T](xs) + } + + implicit def wrapIntArray(xs: Array[Int]): WrappedArray[Int] = if (xs ne null) new WrappedArray.ofInt(xs) else null + implicit def wrapDoubleArray(xs: Array[Double]): WrappedArray[Double] = if (xs ne null) new WrappedArray.ofDouble(xs) else null + implicit def wrapLongArray(xs: Array[Long]): WrappedArray[Long] = if (xs ne null) new WrappedArray.ofLong(xs) else null + implicit def wrapFloatArray(xs: Array[Float]): WrappedArray[Float] = if (xs ne null) new WrappedArray.ofFloat(xs) else null + implicit def wrapCharArray(xs: Array[Char]): WrappedArray[Char] = if (xs ne null) new WrappedArray.ofChar(xs) else null + implicit def wrapByteArray(xs: Array[Byte]): WrappedArray[Byte] = if (xs ne null) new WrappedArray.ofByte(xs) else null + implicit def wrapShortArray(xs: Array[Short]): WrappedArray[Short] = if (xs ne null) new WrappedArray.ofShort(xs) else null + implicit def wrapBooleanArray(xs: Array[Boolean]): WrappedArray[Boolean] = if (xs ne null) new WrappedArray.ofBoolean(xs) else null + implicit def wrapUnitArray(xs: Array[Unit]): WrappedArray[Unit] = if (xs ne null) new WrappedArray.ofUnit(xs) else null + + implicit def wrapString(s: String): WrappedString = if (s ne null) new WrappedString(s) else null + implicit def unwrapString(ws: WrappedString): String = if (ws ne null) ws.self else null + + implicit def fallbackStringCanBuildFrom[T]: CanBuildFrom[String, T, immutable.IndexedSeq[T]] = + new CanBuildFrom[String, T, immutable.IndexedSeq[T]] { + def apply(from: String) = immutable.IndexedSeq.newBuilder[T] + def apply() = immutable.IndexedSeq.newBuilder[T] + } +} diff --git a/src/library/scala/Product.scala b/src/library/scala/Product.scala index 2c6838f6b3..0798587772 100644 --- a/src/library/scala/Product.scala +++ b/src/library/scala/Product.scala @@ -1,6 +1,6 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** +** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** diff --git a/src/library/scala/Product1.scala b/src/library/scala/Product1.scala index edd095c5c6..dbc34ba66a 100644 --- a/src/library/scala/Product1.scala +++ b/src/library/scala/Product1.scala @@ -1,6 +1,6 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** +** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** diff --git a/src/library/scala/Product10.scala b/src/library/scala/Product10.scala index 8daefde699..70de79d49a 100644 --- a/src/library/scala/Product10.scala +++ b/src/library/scala/Product10.scala @@ -1,6 +1,6 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** +** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** diff --git a/src/library/scala/Product11.scala b/src/library/scala/Product11.scala index 90b4e8013e..1bb79ac017 100644 --- a/src/library/scala/Product11.scala +++ b/src/library/scala/Product11.scala @@ -1,6 +1,6 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** +** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** diff --git a/src/library/scala/Product12.scala b/src/library/scala/Product12.scala index d5997ea05a..d7e1e1b05c 100644 --- a/src/library/scala/Product12.scala +++ b/src/library/scala/Product12.scala @@ -1,6 +1,6 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** +** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** diff --git a/src/library/scala/Product13.scala b/src/library/scala/Product13.scala index db8e0f3722..8571b45a40 100644 --- a/src/library/scala/Product13.scala +++ b/src/library/scala/Product13.scala @@ -1,6 +1,6 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** +** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** diff --git a/src/library/scala/Product14.scala b/src/library/scala/Product14.scala index 113c07e8c4..a2f5140370 100644 --- a/src/library/scala/Product14.scala +++ b/src/library/scala/Product14.scala @@ -1,6 +1,6 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** +** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** diff --git a/src/library/scala/Product15.scala b/src/library/scala/Product15.scala index a6ad9c7594..1c6ad0011c 100644 --- a/src/library/scala/Product15.scala +++ b/src/library/scala/Product15.scala @@ -1,6 +1,6 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** +** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** diff --git a/src/library/scala/Product16.scala b/src/library/scala/Product16.scala index cbf47ece94..f03b0b34a2 100644 --- a/src/library/scala/Product16.scala +++ b/src/library/scala/Product16.scala @@ -1,6 +1,6 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** +** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** diff --git a/src/library/scala/Product17.scala b/src/library/scala/Product17.scala index f56836bfd8..72df1b496a 100644 --- a/src/library/scala/Product17.scala +++ b/src/library/scala/Product17.scala @@ -1,6 +1,6 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** +** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** diff --git a/src/library/scala/Product18.scala b/src/library/scala/Product18.scala index 5b86bcff65..0402f90a01 100644 --- a/src/library/scala/Product18.scala +++ b/src/library/scala/Product18.scala @@ -1,6 +1,6 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** +** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** diff --git a/src/library/scala/Product19.scala b/src/library/scala/Product19.scala index ed4bf36c93..b9770db47b 100644 --- a/src/library/scala/Product19.scala +++ b/src/library/scala/Product19.scala @@ -1,6 +1,6 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** +** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** diff --git a/src/library/scala/Product2.scala b/src/library/scala/Product2.scala index e27e54eff9..a43a4a285c 100644 --- a/src/library/scala/Product2.scala +++ b/src/library/scala/Product2.scala @@ -1,6 +1,6 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** +** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** diff --git a/src/library/scala/Product20.scala b/src/library/scala/Product20.scala index 47437a20af..7b0df201ec 100644 --- a/src/library/scala/Product20.scala +++ b/src/library/scala/Product20.scala @@ -1,6 +1,6 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** +** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** diff --git a/src/library/scala/Product21.scala b/src/library/scala/Product21.scala index 319d2725c0..f81347aac0 100644 --- a/src/library/scala/Product21.scala +++ b/src/library/scala/Product21.scala @@ -1,6 +1,6 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** +** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** diff --git a/src/library/scala/Product22.scala b/src/library/scala/Product22.scala index 6ab3737acd..7a25891c6e 100644 --- a/src/library/scala/Product22.scala +++ b/src/library/scala/Product22.scala @@ -1,6 +1,6 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** +** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** diff --git a/src/library/scala/Product3.scala b/src/library/scala/Product3.scala index 1cfbd7956b..9976240935 100644 --- a/src/library/scala/Product3.scala +++ b/src/library/scala/Product3.scala @@ -1,6 +1,6 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** +** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** diff --git a/src/library/scala/Product4.scala b/src/library/scala/Product4.scala index 843571fd60..d6c1543390 100644 --- a/src/library/scala/Product4.scala +++ b/src/library/scala/Product4.scala @@ -1,6 +1,6 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** +** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** diff --git a/src/library/scala/Product5.scala b/src/library/scala/Product5.scala index df73bba3dd..5f1b11a30d 100644 --- a/src/library/scala/Product5.scala +++ b/src/library/scala/Product5.scala @@ -1,6 +1,6 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** +** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** diff --git a/src/library/scala/Product6.scala b/src/library/scala/Product6.scala index 36906ca54e..efd9408d73 100644 --- a/src/library/scala/Product6.scala +++ b/src/library/scala/Product6.scala @@ -1,6 +1,6 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** +** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** diff --git a/src/library/scala/Product7.scala b/src/library/scala/Product7.scala index e7b2c13ad1..fab0a997a1 100644 --- a/src/library/scala/Product7.scala +++ b/src/library/scala/Product7.scala @@ -1,6 +1,6 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** +** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** diff --git a/src/library/scala/Product8.scala b/src/library/scala/Product8.scala index 916e57ec39..41391f7050 100644 --- a/src/library/scala/Product8.scala +++ b/src/library/scala/Product8.scala @@ -1,6 +1,6 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** +** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** diff --git a/src/library/scala/Product9.scala b/src/library/scala/Product9.scala index d5e72edc0b..e22538e1ee 100644 --- a/src/library/scala/Product9.scala +++ b/src/library/scala/Product9.scala @@ -1,6 +1,6 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** +** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** diff --git a/src/library/scala/Proxy.scala b/src/library/scala/Proxy.scala index 07fa6e2e8d..7c28e6ea28 100644 --- a/src/library/scala/Proxy.scala +++ b/src/library/scala/Proxy.scala @@ -28,7 +28,7 @@ trait Proxy extends Any { override def hashCode: Int = self.hashCode override def equals(that: Any): Boolean = that match { case null => false - case _ => + case _ => val x = that.asInstanceOf[AnyRef] (x eq this.asInstanceOf[AnyRef]) || (x eq self.asInstanceOf[AnyRef]) || (x equals self) } diff --git a/src/library/scala/Responder.scala b/src/library/scala/Responder.scala index 0a42ddb0ea..8a658e252a 100644 --- a/src/library/scala/Responder.scala +++ b/src/library/scala/Responder.scala @@ -18,6 +18,7 @@ package scala * @see class Responder * @since 2.1 */ +@deprecated("This object will be removed", "2.11.0") object Responder { /** Creates a responder that answer continuations with the constant `a`. @@ -58,6 +59,7 @@ object Responder { * @version 1.0 * @since 2.1 */ +@deprecated("This class will be removed", "2.11.0") abstract class Responder[+A] extends Serializable { def respond(k: A => Unit): Unit diff --git a/src/library/scala/SerialVersionUID.scala b/src/library/scala/SerialVersionUID.scala index 1f7d047060..77094f0bbf 100644 --- a/src/library/scala/SerialVersionUID.scala +++ b/src/library/scala/SerialVersionUID.scala @@ -12,4 +12,4 @@ package scala * Annotation for specifying the `static SerialVersionUID` field * of a serializable class. */ -class SerialVersionUID(uid: Long) extends scala.annotation.StaticAnnotation +class SerialVersionUID(value: Long) extends scala.annotation.ClassfileAnnotation diff --git a/src/library/scala/Short.scala b/src/library/scala/Short.scala index 35c5fe3ff0..36b9ec4df9 100644 --- a/src/library/scala/Short.scala +++ b/src/library/scala/Short.scala @@ -1,17 +1,17 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** +** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** \* */ -// DO NOT EDIT, CHANGES WILL BE LOST. +// DO NOT EDIT, CHANGES WILL BE LOST +// This auto-generated code can be modified in scala.tools.cmd.gen. +// Afterwards, running tools/codegen-anyvals regenerates this source file. package scala -import scala.language.implicitConversions - /** `Short`, a 16-bit signed integer (equivalent to Java's `short` primitive type) is a * subtype of [[scala.AnyVal]]. Instances of `Short` are not * represented by an object in the underlying runtime system. @@ -37,13 +37,9 @@ final abstract class Short private extends AnyVal { * }}} */ def unary_~ : Int - /** - * Returns this value, unmodified. - */ + /** Returns this value, unmodified. */ def unary_+ : Int - /** - * Returns the negation of this value. - */ + /** Returns the negation of this value. */ def unary_- : Int def +(x: String): String @@ -105,178 +101,94 @@ final abstract class Short private extends AnyVal { */ def >>(x: Long): Int - /** - * Returns `true` if this value is equal to x, `false` otherwise. - */ + /** Returns `true` if this value is equal to x, `false` otherwise. */ def ==(x: Byte): Boolean - /** - * Returns `true` if this value is equal to x, `false` otherwise. - */ + /** Returns `true` if this value is equal to x, `false` otherwise. */ def ==(x: Short): Boolean - /** - * Returns `true` if this value is equal to x, `false` otherwise. - */ + /** Returns `true` if this value is equal to x, `false` otherwise. */ def ==(x: Char): Boolean - /** - * Returns `true` if this value is equal to x, `false` otherwise. - */ + /** Returns `true` if this value is equal to x, `false` otherwise. */ def ==(x: Int): Boolean - /** - * Returns `true` if this value is equal to x, `false` otherwise. - */ + /** Returns `true` if this value is equal to x, `false` otherwise. */ def ==(x: Long): Boolean - /** - * Returns `true` if this value is equal to x, `false` otherwise. - */ + /** Returns `true` if this value is equal to x, `false` otherwise. */ def ==(x: Float): Boolean - /** - * Returns `true` if this value is equal to x, `false` otherwise. - */ + /** Returns `true` if this value is equal to x, `false` otherwise. */ def ==(x: Double): Boolean - /** - * Returns `true` if this value is not equal to x, `false` otherwise. - */ + /** Returns `true` if this value is not equal to x, `false` otherwise. */ def !=(x: Byte): Boolean - /** - * Returns `true` if this value is not equal to x, `false` otherwise. - */ + /** Returns `true` if this value is not equal to x, `false` otherwise. */ def !=(x: Short): Boolean - /** - * Returns `true` if this value is not equal to x, `false` otherwise. - */ + /** Returns `true` if this value is not equal to x, `false` otherwise. */ def !=(x: Char): Boolean - /** - * Returns `true` if this value is not equal to x, `false` otherwise. - */ + /** Returns `true` if this value is not equal to x, `false` otherwise. */ def !=(x: Int): Boolean - /** - * Returns `true` if this value is not equal to x, `false` otherwise. - */ + /** Returns `true` if this value is not equal to x, `false` otherwise. */ def !=(x: Long): Boolean - /** - * Returns `true` if this value is not equal to x, `false` otherwise. - */ + /** Returns `true` if this value is not equal to x, `false` otherwise. */ def !=(x: Float): Boolean - /** - * Returns `true` if this value is not equal to x, `false` otherwise. - */ + /** Returns `true` if this value is not equal to x, `false` otherwise. */ def !=(x: Double): Boolean - /** - * Returns `true` if this value is less than x, `false` otherwise. - */ + /** Returns `true` if this value is less than x, `false` otherwise. */ def <(x: Byte): Boolean - /** - * Returns `true` if this value is less than x, `false` otherwise. - */ + /** Returns `true` if this value is less than x, `false` otherwise. */ def <(x: Short): Boolean - /** - * Returns `true` if this value is less than x, `false` otherwise. - */ + /** Returns `true` if this value is less than x, `false` otherwise. */ def <(x: Char): Boolean - /** - * Returns `true` if this value is less than x, `false` otherwise. - */ + /** Returns `true` if this value is less than x, `false` otherwise. */ def <(x: Int): Boolean - /** - * Returns `true` if this value is less than x, `false` otherwise. - */ + /** Returns `true` if this value is less than x, `false` otherwise. */ def <(x: Long): Boolean - /** - * Returns `true` if this value is less than x, `false` otherwise. - */ + /** Returns `true` if this value is less than x, `false` otherwise. */ def <(x: Float): Boolean - /** - * Returns `true` if this value is less than x, `false` otherwise. - */ + /** Returns `true` if this value is less than x, `false` otherwise. */ def <(x: Double): Boolean - /** - * Returns `true` if this value is less than or equal to x, `false` otherwise. - */ + /** Returns `true` if this value is less than or equal to x, `false` otherwise. */ def <=(x: Byte): Boolean - /** - * Returns `true` if this value is less than or equal to x, `false` otherwise. - */ + /** Returns `true` if this value is less than or equal to x, `false` otherwise. */ def <=(x: Short): Boolean - /** - * Returns `true` if this value is less than or equal to x, `false` otherwise. - */ + /** Returns `true` if this value is less than or equal to x, `false` otherwise. */ def <=(x: Char): Boolean - /** - * Returns `true` if this value is less than or equal to x, `false` otherwise. - */ + /** Returns `true` if this value is less than or equal to x, `false` otherwise. */ def <=(x: Int): Boolean - /** - * Returns `true` if this value is less than or equal to x, `false` otherwise. - */ + /** Returns `true` if this value is less than or equal to x, `false` otherwise. */ def <=(x: Long): Boolean - /** - * Returns `true` if this value is less than or equal to x, `false` otherwise. - */ + /** Returns `true` if this value is less than or equal to x, `false` otherwise. */ def <=(x: Float): Boolean - /** - * Returns `true` if this value is less than or equal to x, `false` otherwise. - */ + /** Returns `true` if this value is less than or equal to x, `false` otherwise. */ def <=(x: Double): Boolean - /** - * Returns `true` if this value is greater than x, `false` otherwise. - */ + /** Returns `true` if this value is greater than x, `false` otherwise. */ def >(x: Byte): Boolean - /** - * Returns `true` if this value is greater than x, `false` otherwise. - */ + /** Returns `true` if this value is greater than x, `false` otherwise. */ def >(x: Short): Boolean - /** - * Returns `true` if this value is greater than x, `false` otherwise. - */ + /** Returns `true` if this value is greater than x, `false` otherwise. */ def >(x: Char): Boolean - /** - * Returns `true` if this value is greater than x, `false` otherwise. - */ + /** Returns `true` if this value is greater than x, `false` otherwise. */ def >(x: Int): Boolean - /** - * Returns `true` if this value is greater than x, `false` otherwise. - */ + /** Returns `true` if this value is greater than x, `false` otherwise. */ def >(x: Long): Boolean - /** - * Returns `true` if this value is greater than x, `false` otherwise. - */ + /** Returns `true` if this value is greater than x, `false` otherwise. */ def >(x: Float): Boolean - /** - * Returns `true` if this value is greater than x, `false` otherwise. - */ + /** Returns `true` if this value is greater than x, `false` otherwise. */ def >(x: Double): Boolean - /** - * Returns `true` if this value is greater than or equal to x, `false` otherwise. - */ + /** Returns `true` if this value is greater than or equal to x, `false` otherwise. */ def >=(x: Byte): Boolean - /** - * Returns `true` if this value is greater than or equal to x, `false` otherwise. - */ + /** Returns `true` if this value is greater than or equal to x, `false` otherwise. */ def >=(x: Short): Boolean - /** - * Returns `true` if this value is greater than or equal to x, `false` otherwise. - */ + /** Returns `true` if this value is greater than or equal to x, `false` otherwise. */ def >=(x: Char): Boolean - /** - * Returns `true` if this value is greater than or equal to x, `false` otherwise. - */ + /** Returns `true` if this value is greater than or equal to x, `false` otherwise. */ def >=(x: Int): Boolean - /** - * Returns `true` if this value is greater than or equal to x, `false` otherwise. - */ + /** Returns `true` if this value is greater than or equal to x, `false` otherwise. */ def >=(x: Long): Boolean - /** - * Returns `true` if this value is greater than or equal to x, `false` otherwise. - */ + /** Returns `true` if this value is greater than or equal to x, `false` otherwise. */ def >=(x: Float): Boolean - /** - * Returns `true` if this value is greater than or equal to x, `false` otherwise. - */ + /** Returns `true` if this value is greater than or equal to x, `false` otherwise. */ def >=(x: Double): Boolean /** @@ -447,165 +359,95 @@ final abstract class Short private extends AnyVal { */ def ^(x: Long): Long - /** - * Returns the sum of this value and `x`. - */ + /** Returns the sum of this value and `x`. */ def +(x: Byte): Int - /** - * Returns the sum of this value and `x`. - */ + /** Returns the sum of this value and `x`. */ def +(x: Short): Int - /** - * Returns the sum of this value and `x`. - */ + /** Returns the sum of this value and `x`. */ def +(x: Char): Int - /** - * Returns the sum of this value and `x`. - */ + /** Returns the sum of this value and `x`. */ def +(x: Int): Int - /** - * Returns the sum of this value and `x`. - */ + /** Returns the sum of this value and `x`. */ def +(x: Long): Long - /** - * Returns the sum of this value and `x`. - */ + /** Returns the sum of this value and `x`. */ def +(x: Float): Float - /** - * Returns the sum of this value and `x`. - */ + /** Returns the sum of this value and `x`. */ def +(x: Double): Double - /** - * Returns the difference of this value and `x`. - */ + /** Returns the difference of this value and `x`. */ def -(x: Byte): Int - /** - * Returns the difference of this value and `x`. - */ + /** Returns the difference of this value and `x`. */ def -(x: Short): Int - /** - * Returns the difference of this value and `x`. - */ + /** Returns the difference of this value and `x`. */ def -(x: Char): Int - /** - * Returns the difference of this value and `x`. - */ + /** Returns the difference of this value and `x`. */ def -(x: Int): Int - /** - * Returns the difference of this value and `x`. - */ + /** Returns the difference of this value and `x`. */ def -(x: Long): Long - /** - * Returns the difference of this value and `x`. - */ + /** Returns the difference of this value and `x`. */ def -(x: Float): Float - /** - * Returns the difference of this value and `x`. - */ + /** Returns the difference of this value and `x`. */ def -(x: Double): Double - /** - * Returns the product of this value and `x`. - */ + /** Returns the product of this value and `x`. */ def *(x: Byte): Int - /** - * Returns the product of this value and `x`. - */ + /** Returns the product of this value and `x`. */ def *(x: Short): Int - /** - * Returns the product of this value and `x`. - */ + /** Returns the product of this value and `x`. */ def *(x: Char): Int - /** - * Returns the product of this value and `x`. - */ + /** Returns the product of this value and `x`. */ def *(x: Int): Int - /** - * Returns the product of this value and `x`. - */ + /** Returns the product of this value and `x`. */ def *(x: Long): Long - /** - * Returns the product of this value and `x`. - */ + /** Returns the product of this value and `x`. */ def *(x: Float): Float - /** - * Returns the product of this value and `x`. - */ + /** Returns the product of this value and `x`. */ def *(x: Double): Double - /** - * Returns the quotient of this value and `x`. - */ + /** Returns the quotient of this value and `x`. */ def /(x: Byte): Int - /** - * Returns the quotient of this value and `x`. - */ + /** Returns the quotient of this value and `x`. */ def /(x: Short): Int - /** - * Returns the quotient of this value and `x`. - */ + /** Returns the quotient of this value and `x`. */ def /(x: Char): Int - /** - * Returns the quotient of this value and `x`. - */ + /** Returns the quotient of this value and `x`. */ def /(x: Int): Int - /** - * Returns the quotient of this value and `x`. - */ + /** Returns the quotient of this value and `x`. */ def /(x: Long): Long - /** - * Returns the quotient of this value and `x`. - */ + /** Returns the quotient of this value and `x`. */ def /(x: Float): Float - /** - * Returns the quotient of this value and `x`. - */ + /** Returns the quotient of this value and `x`. */ def /(x: Double): Double - /** - * Returns the remainder of the division of this value by `x`. - */ + /** Returns the remainder of the division of this value by `x`. */ def %(x: Byte): Int - /** - * Returns the remainder of the division of this value by `x`. - */ + /** Returns the remainder of the division of this value by `x`. */ def %(x: Short): Int - /** - * Returns the remainder of the division of this value by `x`. - */ + /** Returns the remainder of the division of this value by `x`. */ def %(x: Char): Int - /** - * Returns the remainder of the division of this value by `x`. - */ + /** Returns the remainder of the division of this value by `x`. */ def %(x: Int): Int - /** - * Returns the remainder of the division of this value by `x`. - */ + /** Returns the remainder of the division of this value by `x`. */ def %(x: Long): Long - /** - * Returns the remainder of the division of this value by `x`. - */ + /** Returns the remainder of the division of this value by `x`. */ def %(x: Float): Float - /** - * Returns the remainder of the division of this value by `x`. - */ + /** Returns the remainder of the division of this value by `x`. */ def %(x: Double): Double override def getClass(): Class[Short] = null } object Short extends AnyValCompanion { - /** The smallest value representable as a Short. - */ + /** The smallest value representable as a Short. */ final val MinValue = java.lang.Short.MIN_VALUE - /** The largest value representable as a Short. - */ + /** The largest value representable as a Short. */ final val MaxValue = java.lang.Short.MAX_VALUE /** Transform a value type into a boxed reference type. * + * Runtime implementation determined by `scala.runtime.BoxesRunTime.boxToShort`. See [[https://github.com/scala/scala src/library/scala/runtime/BoxesRunTime.java]]. + * * @param x the Short to be boxed * @return a java.lang.Short offering `x` as its underlying value. */ @@ -615,18 +457,18 @@ object Short extends AnyValCompanion { * method is not typesafe: it accepts any Object, but will throw * an exception if the argument is not a java.lang.Short. * + * Runtime implementation determined by `scala.runtime.BoxesRunTime.unboxToShort`. See [[https://github.com/scala/scala src/library/scala/runtime/BoxesRunTime.java]]. + * * @param x the java.lang.Short to be unboxed. * @throws ClassCastException if the argument is not a java.lang.Short * @return the Short resulting from calling shortValue() on `x` */ def unbox(x: java.lang.Object): Short = x.asInstanceOf[java.lang.Short].shortValue() - /** The String representation of the scala.Short companion object. - */ + /** The String representation of the scala.Short companion object. */ override def toString = "object scala.Short" - - /** Language mandated coercions from Short to "wider" types. - */ + /** Language mandated coercions from Short to "wider" types. */ + import scala.language.implicitConversions implicit def short2int(x: Short): Int = x.toInt implicit def short2long(x: Short): Long = x.toLong implicit def short2float(x: Short): Float = x.toFloat diff --git a/src/library/scala/Specializable.scala b/src/library/scala/Specializable.scala index c7a6091a65..137598c28d 100644 --- a/src/library/scala/Specializable.scala +++ b/src/library/scala/Specializable.scala @@ -11,7 +11,7 @@ package scala /** A common supertype for companions of specializable types. * Should not be extended in user code. */ -trait Specializable extends SpecializableCompanion +trait Specializable object Specializable { // No type parameter in @specialized annotation. diff --git a/src/library/scala/SpecializableCompanion.scala b/src/library/scala/SpecializableCompanion.scala deleted file mode 100644 index 1a9ce71d2a..0000000000 --- a/src/library/scala/SpecializableCompanion.scala +++ /dev/null @@ -1,14 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala - -/** A common supertype for companion classes which specialization takes into account. - */ -@deprecated("Use Specializable instead", "2.10.0") -private[scala] trait SpecializableCompanion diff --git a/src/library/scala/StringContext.scala b/src/library/scala/StringContext.scala index 1b5fd6c8d3..c0468e8b02 100644 --- a/src/library/scala/StringContext.scala +++ b/src/library/scala/StringContext.scala @@ -8,6 +8,9 @@ package scala +import java.lang.{ StringBuilder => JLSBuilder } +import scala.annotation.tailrec + /** This class provides the basic mechanism to do String Interpolation. * String Interpolation allows users * to embed variable references directly in *processed* string literals. @@ -41,7 +44,7 @@ package scala * val x: JSONObject = json"{ a: $a }" * }}} * - * Here the `JsonHelper` extenion class implicitly adds the `json` method to + * Here the `JsonHelper` extension class implicitly adds the `json` method to * `StringContext` which can be used for `json` string literals. * * @since 2.10.0 @@ -59,7 +62,8 @@ case class StringContext(parts: String*) { */ def checkLengths(args: Seq[Any]): Unit = if (parts.length != args.length + 1) - throw new IllegalArgumentException("wrong number of arguments for interpolated string") + throw new IllegalArgumentException("wrong number of arguments ("+ args.length + +") for interpolated string with "+ parts.length +" parts") /** The simple string interpolator. @@ -117,7 +121,7 @@ case class StringContext(parts: String*) { checkLengths(args) val pi = parts.iterator val ai = args.iterator - val bldr = new java.lang.StringBuilder(process(pi.next())) + val bldr = new JLSBuilder(process(pi.next())) while (ai.hasNext) { bldr append ai.next bldr append process(pi.next()) @@ -156,13 +160,12 @@ case class StringContext(parts: String*) { * If a formatting position does not refer to a `%` character (which is assumed to * start a format specifier), then the string format specifier `%s` is inserted. * - * 2. Any `%` characters not in formatting positions are left in the resulting - * string literally. This is achieved by replacing each such occurrence by the - * format specifier `%%`. + * 2. Any `%` characters not in formatting positions must begin one of the conversions + * `%%` (the literal percent) or `%n` (the platform-specific line separator). */ // The implementation is hardwired to `scala.tools.reflect.MacroImplementations.macro_StringInterpolation_f` // Using the mechanism implemented in `scala.tools.reflect.FastTrack` - def f(args: Any*): String = ??? // macro + def f(args: Any*): String = macro ??? } object StringContext { @@ -172,8 +175,8 @@ object StringContext { * @param str The offending string * @param idx The index of the offending backslash character in `str`. */ - class InvalidEscapeException(str: String, idx: Int) - extends IllegalArgumentException("invalid escape character at index "+idx+" in \""+str+"\"") + class InvalidEscapeException(str: String, @deprecatedName('idx) val index: Int) + extends IllegalArgumentException("invalid escape character at index "+index+" in \""+str+"\"") /** Expands standard Scala escape sequences in a string. * Escape sequences are: @@ -184,57 +187,62 @@ object StringContext { * @param str A string that may contain escape sequences * @return The string with all escape sequences expanded. */ - def treatEscapes(str: String): String = { - lazy val bldr = new java.lang.StringBuilder + def treatEscapes(str: String): String = treatEscapes0(str, strict = false) + + /** Treats escapes, but disallows octal escape sequences. */ + def processEscapes(str: String): String = treatEscapes0(str, strict = true) + + private def treatEscapes0(str: String, strict: Boolean): String = { val len = str.length - var start = 0 - var cur = 0 - var idx = 0 - def output(ch: Char) = { - bldr.append(str, start, cur) - bldr append ch - start = idx - } - while (idx < len) { - cur = idx - if (str(idx) == '\\') { - idx += 1 - if (idx >= len) throw new InvalidEscapeException(str, cur) - if ('0' <= str(idx) && str(idx) <= '7') { - val leadch = str(idx) - var oct = leadch - '0' - idx += 1 - if (idx < len && '0' <= str(idx) && str(idx) <= '7') { - oct = oct * 8 + str(idx) - '0' - idx += 1 - if (idx < len && leadch <= '3' && '0' <= str(idx) && str(idx) <= '7') { - oct = oct * 8 + str(idx) - '0' + // replace escapes with given first escape + def replace(first: Int): String = { + val b = new JLSBuilder + // append replacement starting at index `i`, with `next` backslash + @tailrec def loop(i: Int, next: Int): String = { + if (next >= 0) { + //require(str(next) == '\\') + if (next > i) b.append(str, i, next) + var idx = next + 1 + if (idx >= len) throw new InvalidEscapeException(str, next) + val c = str(idx) match { + case 'b' => '\b' + case 't' => '\t' + case 'n' => '\n' + case 'f' => '\f' + case 'r' => '\r' + case '"' => '"' + case '\'' => '\'' + case '\\' => '\\' + case o if '0' <= o && o <= '7' => + if (strict) throw new InvalidEscapeException(str, next) + val leadch = str(idx) + var oct = leadch - '0' idx += 1 - } + if (idx < len && '0' <= str(idx) && str(idx) <= '7') { + oct = oct * 8 + str(idx) - '0' + idx += 1 + if (idx < len && leadch <= '3' && '0' <= str(idx) && str(idx) <= '7') { + oct = oct * 8 + str(idx) - '0' + idx += 1 + } + } + idx -= 1 // retreat + oct.toChar + case _ => throw new InvalidEscapeException(str, next) } - output(oct.toChar) + idx += 1 // advance + b append c + loop(idx, str.indexOf('\\', idx)) } else { - val ch = str(idx) - idx += 1 - output { - ch match { - case 'b' => '\b' - case 't' => '\t' - case 'n' => '\n' - case 'f' => '\f' - case 'r' => '\r' - case '\"' => '\"' - case '\'' => '\'' - case '\\' => '\\' - case _ => throw new InvalidEscapeException(str, cur) - } - } + if (i < len) b.append(str, i, len) + b.toString } - } else { - idx += 1 } + loop(0, first) + } + str indexOf '\\' match { + case -1 => str + case i => replace(i) } - if (start == 0) str - else bldr.append(str, start, idx).toString } } diff --git a/src/library/scala/Tuple1.scala b/src/library/scala/Tuple1.scala index 02fdd0cba5..5898b63e21 100644 --- a/src/library/scala/Tuple1.scala +++ b/src/library/scala/Tuple1.scala @@ -1,6 +1,6 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** +** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** @@ -15,6 +15,7 @@ package scala * @constructor Create a new tuple with 1 elements. * @param _1 Element 1 of this Tuple1 */ +@deprecatedInheritance("Tuples will be made final in a future version.", "2.11.0") case class Tuple1[@specialized(Int, Long, Double) +T1](_1: T1) extends Product1[T1] { diff --git a/src/library/scala/Tuple10.scala b/src/library/scala/Tuple10.scala index ba2a02a8b2..2b0239561d 100644 --- a/src/library/scala/Tuple10.scala +++ b/src/library/scala/Tuple10.scala @@ -1,6 +1,6 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** +** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** @@ -24,6 +24,7 @@ package scala * @param _9 Element 9 of this Tuple10 * @param _10 Element 10 of this Tuple10 */ +@deprecatedInheritance("Tuples will be made final in a future version.", "2.11.0") case class Tuple10[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10](_1: T1, _2: T2, _3: T3, _4: T4, _5: T5, _6: T6, _7: T7, _8: T8, _9: T9, _10: T10) extends Product10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10] { diff --git a/src/library/scala/Tuple11.scala b/src/library/scala/Tuple11.scala index 7f51d172d4..0d5294d547 100644 --- a/src/library/scala/Tuple11.scala +++ b/src/library/scala/Tuple11.scala @@ -1,6 +1,6 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** +** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** @@ -25,6 +25,7 @@ package scala * @param _10 Element 10 of this Tuple11 * @param _11 Element 11 of this Tuple11 */ +@deprecatedInheritance("Tuples will be made final in a future version.", "2.11.0") case class Tuple11[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11](_1: T1, _2: T2, _3: T3, _4: T4, _5: T5, _6: T6, _7: T7, _8: T8, _9: T9, _10: T10, _11: T11) extends Product11[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11] { diff --git a/src/library/scala/Tuple12.scala b/src/library/scala/Tuple12.scala index 4bbc6a0eab..d36c8275c1 100644 --- a/src/library/scala/Tuple12.scala +++ b/src/library/scala/Tuple12.scala @@ -1,6 +1,6 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** +** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** @@ -26,6 +26,7 @@ package scala * @param _11 Element 11 of this Tuple12 * @param _12 Element 12 of this Tuple12 */ +@deprecatedInheritance("Tuples will be made final in a future version.", "2.11.0") case class Tuple12[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12](_1: T1, _2: T2, _3: T3, _4: T4, _5: T5, _6: T6, _7: T7, _8: T8, _9: T9, _10: T10, _11: T11, _12: T12) extends Product12[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12] { diff --git a/src/library/scala/Tuple13.scala b/src/library/scala/Tuple13.scala index 77bd59bf2e..edc37456fe 100644 --- a/src/library/scala/Tuple13.scala +++ b/src/library/scala/Tuple13.scala @@ -1,6 +1,6 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** +** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** @@ -27,6 +27,7 @@ package scala * @param _12 Element 12 of this Tuple13 * @param _13 Element 13 of this Tuple13 */ +@deprecatedInheritance("Tuples will be made final in a future version.", "2.11.0") case class Tuple13[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, +T13](_1: T1, _2: T2, _3: T3, _4: T4, _5: T5, _6: T6, _7: T7, _8: T8, _9: T9, _10: T10, _11: T11, _12: T12, _13: T13) extends Product13[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13] { diff --git a/src/library/scala/Tuple14.scala b/src/library/scala/Tuple14.scala index bf7a4ce016..9896e736c9 100644 --- a/src/library/scala/Tuple14.scala +++ b/src/library/scala/Tuple14.scala @@ -1,6 +1,6 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** +** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** @@ -28,6 +28,7 @@ package scala * @param _13 Element 13 of this Tuple14 * @param _14 Element 14 of this Tuple14 */ +@deprecatedInheritance("Tuples will be made final in a future version.", "2.11.0") case class Tuple14[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, +T13, +T14](_1: T1, _2: T2, _3: T3, _4: T4, _5: T5, _6: T6, _7: T7, _8: T8, _9: T9, _10: T10, _11: T11, _12: T12, _13: T13, _14: T14) extends Product14[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14] { diff --git a/src/library/scala/Tuple15.scala b/src/library/scala/Tuple15.scala index 582c359bc6..45cd4f751f 100644 --- a/src/library/scala/Tuple15.scala +++ b/src/library/scala/Tuple15.scala @@ -1,6 +1,6 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** +** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** @@ -29,6 +29,7 @@ package scala * @param _14 Element 14 of this Tuple15 * @param _15 Element 15 of this Tuple15 */ +@deprecatedInheritance("Tuples will be made final in a future version.", "2.11.0") case class Tuple15[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, +T13, +T14, +T15](_1: T1, _2: T2, _3: T3, _4: T4, _5: T5, _6: T6, _7: T7, _8: T8, _9: T9, _10: T10, _11: T11, _12: T12, _13: T13, _14: T14, _15: T15) extends Product15[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15] { diff --git a/src/library/scala/Tuple16.scala b/src/library/scala/Tuple16.scala index a1e9a790ff..2e370a5b31 100644 --- a/src/library/scala/Tuple16.scala +++ b/src/library/scala/Tuple16.scala @@ -1,6 +1,6 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** +** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** @@ -30,6 +30,7 @@ package scala * @param _15 Element 15 of this Tuple16 * @param _16 Element 16 of this Tuple16 */ +@deprecatedInheritance("Tuples will be made final in a future version.", "2.11.0") case class Tuple16[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, +T13, +T14, +T15, +T16](_1: T1, _2: T2, _3: T3, _4: T4, _5: T5, _6: T6, _7: T7, _8: T8, _9: T9, _10: T10, _11: T11, _12: T12, _13: T13, _14: T14, _15: T15, _16: T16) extends Product16[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16] { diff --git a/src/library/scala/Tuple17.scala b/src/library/scala/Tuple17.scala index f531766c18..2242a15fda 100644 --- a/src/library/scala/Tuple17.scala +++ b/src/library/scala/Tuple17.scala @@ -1,6 +1,6 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** +** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** @@ -31,6 +31,7 @@ package scala * @param _16 Element 16 of this Tuple17 * @param _17 Element 17 of this Tuple17 */ +@deprecatedInheritance("Tuples will be made final in a future version.", "2.11.0") case class Tuple17[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, +T13, +T14, +T15, +T16, +T17](_1: T1, _2: T2, _3: T3, _4: T4, _5: T5, _6: T6, _7: T7, _8: T8, _9: T9, _10: T10, _11: T11, _12: T12, _13: T13, _14: T14, _15: T15, _16: T16, _17: T17) extends Product17[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17] { diff --git a/src/library/scala/Tuple18.scala b/src/library/scala/Tuple18.scala index a96db25e4b..68f245c6ce 100644 --- a/src/library/scala/Tuple18.scala +++ b/src/library/scala/Tuple18.scala @@ -1,6 +1,6 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** +** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** @@ -32,6 +32,7 @@ package scala * @param _17 Element 17 of this Tuple18 * @param _18 Element 18 of this Tuple18 */ +@deprecatedInheritance("Tuples will be made final in a future version.", "2.11.0") case class Tuple18[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, +T13, +T14, +T15, +T16, +T17, +T18](_1: T1, _2: T2, _3: T3, _4: T4, _5: T5, _6: T6, _7: T7, _8: T8, _9: T9, _10: T10, _11: T11, _12: T12, _13: T13, _14: T14, _15: T15, _16: T16, _17: T17, _18: T18) extends Product18[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18] { diff --git a/src/library/scala/Tuple19.scala b/src/library/scala/Tuple19.scala index 718280d68a..a8a49549fb 100644 --- a/src/library/scala/Tuple19.scala +++ b/src/library/scala/Tuple19.scala @@ -1,6 +1,6 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** +** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** @@ -33,6 +33,7 @@ package scala * @param _18 Element 18 of this Tuple19 * @param _19 Element 19 of this Tuple19 */ +@deprecatedInheritance("Tuples will be made final in a future version.", "2.11.0") case class Tuple19[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, +T13, +T14, +T15, +T16, +T17, +T18, +T19](_1: T1, _2: T2, _3: T3, _4: T4, _5: T5, _6: T6, _7: T7, _8: T8, _9: T9, _10: T10, _11: T11, _12: T12, _13: T13, _14: T14, _15: T15, _16: T16, _17: T17, _18: T18, _19: T19) extends Product19[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19] { diff --git a/src/library/scala/Tuple2.scala b/src/library/scala/Tuple2.scala index 35d5a441c8..9ea1469c5c 100644 --- a/src/library/scala/Tuple2.scala +++ b/src/library/scala/Tuple2.scala @@ -1,6 +1,6 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** +** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** @@ -16,6 +16,7 @@ package scala * @param _1 Element 1 of this Tuple2 * @param _2 Element 2 of this Tuple2 */ +@deprecatedInheritance("Tuples will be made final in a future version.", "2.11.0") case class Tuple2[@specialized(Int, Long, Double, Char, Boolean/*, AnyRef*/) +T1, @specialized(Int, Long, Double, Char, Boolean/*, AnyRef*/) +T2](_1: T1, _2: T2) extends Product2[T1, T2] { diff --git a/src/library/scala/Tuple20.scala b/src/library/scala/Tuple20.scala index 4a44c0bb89..0118d382ab 100644 --- a/src/library/scala/Tuple20.scala +++ b/src/library/scala/Tuple20.scala @@ -1,6 +1,6 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** +** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** @@ -34,6 +34,7 @@ package scala * @param _19 Element 19 of this Tuple20 * @param _20 Element 20 of this Tuple20 */ +@deprecatedInheritance("Tuples will be made final in a future version.", "2.11.0") case class Tuple20[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, +T13, +T14, +T15, +T16, +T17, +T18, +T19, +T20](_1: T1, _2: T2, _3: T3, _4: T4, _5: T5, _6: T6, _7: T7, _8: T8, _9: T9, _10: T10, _11: T11, _12: T12, _13: T13, _14: T14, _15: T15, _16: T16, _17: T17, _18: T18, _19: T19, _20: T20) extends Product20[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20] { diff --git a/src/library/scala/Tuple21.scala b/src/library/scala/Tuple21.scala index 580a169e39..ceae94af41 100644 --- a/src/library/scala/Tuple21.scala +++ b/src/library/scala/Tuple21.scala @@ -1,6 +1,6 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** +** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** @@ -35,6 +35,7 @@ package scala * @param _20 Element 20 of this Tuple21 * @param _21 Element 21 of this Tuple21 */ +@deprecatedInheritance("Tuples will be made final in a future version.", "2.11.0") case class Tuple21[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, +T13, +T14, +T15, +T16, +T17, +T18, +T19, +T20, +T21](_1: T1, _2: T2, _3: T3, _4: T4, _5: T5, _6: T6, _7: T7, _8: T8, _9: T9, _10: T10, _11: T11, _12: T12, _13: T13, _14: T14, _15: T15, _16: T16, _17: T17, _18: T18, _19: T19, _20: T20, _21: T21) extends Product21[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21] { diff --git a/src/library/scala/Tuple22.scala b/src/library/scala/Tuple22.scala index fd3392ddea..ecd567a710 100644 --- a/src/library/scala/Tuple22.scala +++ b/src/library/scala/Tuple22.scala @@ -1,6 +1,6 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** +** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** @@ -36,6 +36,7 @@ package scala * @param _21 Element 21 of this Tuple22 * @param _22 Element 22 of this Tuple22 */ +@deprecatedInheritance("Tuples will be made final in a future version.", "2.11.0") case class Tuple22[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, +T13, +T14, +T15, +T16, +T17, +T18, +T19, +T20, +T21, +T22](_1: T1, _2: T2, _3: T3, _4: T4, _5: T5, _6: T6, _7: T7, _8: T8, _9: T9, _10: T10, _11: T11, _12: T12, _13: T13, _14: T14, _15: T15, _16: T16, _17: T17, _18: T18, _19: T19, _20: T20, _21: T21, _22: T22) extends Product22[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22] { diff --git a/src/library/scala/Tuple3.scala b/src/library/scala/Tuple3.scala index 5ed13602e3..6e71d3ae8c 100644 --- a/src/library/scala/Tuple3.scala +++ b/src/library/scala/Tuple3.scala @@ -1,6 +1,6 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** +** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** @@ -17,6 +17,7 @@ package scala * @param _2 Element 2 of this Tuple3 * @param _3 Element 3 of this Tuple3 */ +@deprecatedInheritance("Tuples will be made final in a future version.", "2.11.0") case class Tuple3[+T1, +T2, +T3](_1: T1, _2: T2, _3: T3) extends Product3[T1, T2, T3] { diff --git a/src/library/scala/Tuple4.scala b/src/library/scala/Tuple4.scala index a859078bcf..4c84cfc674 100644 --- a/src/library/scala/Tuple4.scala +++ b/src/library/scala/Tuple4.scala @@ -1,6 +1,6 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** +** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** @@ -18,6 +18,7 @@ package scala * @param _3 Element 3 of this Tuple4 * @param _4 Element 4 of this Tuple4 */ +@deprecatedInheritance("Tuples will be made final in a future version.", "2.11.0") case class Tuple4[+T1, +T2, +T3, +T4](_1: T1, _2: T2, _3: T3, _4: T4) extends Product4[T1, T2, T3, T4] { diff --git a/src/library/scala/Tuple5.scala b/src/library/scala/Tuple5.scala index 1edfb673ee..fe8e853f12 100644 --- a/src/library/scala/Tuple5.scala +++ b/src/library/scala/Tuple5.scala @@ -1,6 +1,6 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** +** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** @@ -19,6 +19,7 @@ package scala * @param _4 Element 4 of this Tuple5 * @param _5 Element 5 of this Tuple5 */ +@deprecatedInheritance("Tuples will be made final in a future version.", "2.11.0") case class Tuple5[+T1, +T2, +T3, +T4, +T5](_1: T1, _2: T2, _3: T3, _4: T4, _5: T5) extends Product5[T1, T2, T3, T4, T5] { diff --git a/src/library/scala/Tuple6.scala b/src/library/scala/Tuple6.scala index 5b74937e58..6bf1c73d4b 100644 --- a/src/library/scala/Tuple6.scala +++ b/src/library/scala/Tuple6.scala @@ -1,6 +1,6 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** +** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** @@ -20,6 +20,7 @@ package scala * @param _5 Element 5 of this Tuple6 * @param _6 Element 6 of this Tuple6 */ +@deprecatedInheritance("Tuples will be made final in a future version.", "2.11.0") case class Tuple6[+T1, +T2, +T3, +T4, +T5, +T6](_1: T1, _2: T2, _3: T3, _4: T4, _5: T5, _6: T6) extends Product6[T1, T2, T3, T4, T5, T6] { diff --git a/src/library/scala/Tuple7.scala b/src/library/scala/Tuple7.scala index a7f572e9f0..ea42709cb7 100644 --- a/src/library/scala/Tuple7.scala +++ b/src/library/scala/Tuple7.scala @@ -1,6 +1,6 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** +** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** @@ -21,6 +21,7 @@ package scala * @param _6 Element 6 of this Tuple7 * @param _7 Element 7 of this Tuple7 */ +@deprecatedInheritance("Tuples will be made final in a future version.", "2.11.0") case class Tuple7[+T1, +T2, +T3, +T4, +T5, +T6, +T7](_1: T1, _2: T2, _3: T3, _4: T4, _5: T5, _6: T6, _7: T7) extends Product7[T1, T2, T3, T4, T5, T6, T7] { diff --git a/src/library/scala/Tuple8.scala b/src/library/scala/Tuple8.scala index 9bb427d689..c24f9454e0 100644 --- a/src/library/scala/Tuple8.scala +++ b/src/library/scala/Tuple8.scala @@ -1,6 +1,6 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** +** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** @@ -22,6 +22,7 @@ package scala * @param _7 Element 7 of this Tuple8 * @param _8 Element 8 of this Tuple8 */ +@deprecatedInheritance("Tuples will be made final in a future version.", "2.11.0") case class Tuple8[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8](_1: T1, _2: T2, _3: T3, _4: T4, _5: T5, _6: T6, _7: T7, _8: T8) extends Product8[T1, T2, T3, T4, T5, T6, T7, T8] { diff --git a/src/library/scala/Tuple9.scala b/src/library/scala/Tuple9.scala index 4d50539e0c..ed02b30df2 100644 --- a/src/library/scala/Tuple9.scala +++ b/src/library/scala/Tuple9.scala @@ -1,6 +1,6 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** +** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** @@ -23,6 +23,7 @@ package scala * @param _8 Element 8 of this Tuple9 * @param _9 Element 9 of this Tuple9 */ +@deprecatedInheritance("Tuples will be made final in a future version.", "2.11.0") case class Tuple9[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9](_1: T1, _2: T2, _3: T3, _4: T4, _5: T5, _6: T6, _7: T7, _8: T8, _9: T9) extends Product9[T1, T2, T3, T4, T5, T6, T7, T8, T9] { diff --git a/src/library/scala/UninitializedFieldError.scala b/src/library/scala/UninitializedFieldError.scala index 10c6cccf15..0dfba2a187 100644 --- a/src/library/scala/UninitializedFieldError.scala +++ b/src/library/scala/UninitializedFieldError.scala @@ -18,8 +18,6 @@ package scala * * @since 2.7 */ -final case class UninitializedFieldError(msg: String) - extends RuntimeException(msg) { - def this(obj: Any) = - this(if (null != obj) obj.toString() else "null") +final case class UninitializedFieldError(msg: String) extends RuntimeException(msg) { + def this(obj: Any) = this("" + obj) } diff --git a/src/library/scala/Unit.scala b/src/library/scala/Unit.scala index dc67e60314..018ad24a99 100644 --- a/src/library/scala/Unit.scala +++ b/src/library/scala/Unit.scala @@ -1,17 +1,17 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** +** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** \* */ -// DO NOT EDIT, CHANGES WILL BE LOST. +// DO NOT EDIT, CHANGES WILL BE LOST +// This auto-generated code can be modified in scala.tools.cmd.gen. +// Afterwards, running tools/codegen-anyvals regenerates this source file. package scala -import scala.language.implicitConversions - /** `Unit` is a subtype of [[scala.AnyVal]]. There is only one value of type * `Unit`, `()`, and it is not represented by any object in the underlying @@ -41,8 +41,7 @@ object Unit extends AnyValCompanion { */ def unbox(x: java.lang.Object): Unit = () - /** The String representation of the scala.Unit companion object. - */ + /** The String representation of the scala.Unit companion object. */ override def toString = "object scala.Unit" } diff --git a/src/library/scala/annotation/cloneable.scala b/src/library/scala/annotation/cloneable.scala deleted file mode 100644 index 4fb62b698f..0000000000 --- a/src/library/scala/annotation/cloneable.scala +++ /dev/null @@ -1,15 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala.annotation - -/** - * An annotation that designates the class to which it is applied as cloneable - */ -@deprecated("instead of `@cloneable class C`, use `class C extends Cloneable`", "2.10.0") -class cloneable extends scala.annotation.StaticAnnotation diff --git a/src/library/scala/annotation/compileTimeOnly.scala b/src/library/scala/annotation/compileTimeOnly.scala new file mode 100644 index 0000000000..942e9cad8c --- /dev/null +++ b/src/library/scala/annotation/compileTimeOnly.scala @@ -0,0 +1,22 @@ +package scala.annotation + +import scala.annotation.meta._ + +/** + * An annotation that designates that an annottee should not be referred to after + * type checking (which includes macro expansion). + * + * Examples of potential use: + * 1) The annottee can only appear in the arguments of some other macro + * that will eliminate it from the AST during expansion. + * 2) The annottee is a macro and should have been expanded away, + * so if hasn't, something wrong has happened. + * (Comes in handy to provide better support for new macro flavors, + * e.g. macro annotations, that can't be expanded by the vanilla compiler). + * + * @param message the error message to print during compilation if a reference remains + * after type checking + * @since 2.11.0 + */ +@getter @setter @beanGetter @beanSetter @companionClass @companionMethod +final class compileTimeOnly(message: String) extends scala.annotation.StaticAnnotation diff --git a/src/library/scala/annotation/implicitNotFound.scala b/src/library/scala/annotation/implicitNotFound.scala index bbde90cebb..eeedcb014e 100644 --- a/src/library/scala/annotation/implicitNotFound.scala +++ b/src/library/scala/annotation/implicitNotFound.scala @@ -9,8 +9,11 @@ package scala.annotation /** - * An annotation that specifies the error message that is emitted when the compiler - * cannot find an implicit value of the annotated type. + * To customize the error message that's emitted when an implicit of type + * C[T1,..., TN] cannot be found, annotate the class C with @implicitNotFound. + * Assuming C has type parameters X1,..., XN, the error message will be the + * result of replacing all occurrences of ${Xi} in the string msg with the + * string representation of the corresponding type argument Ti. * * * @author Adriaan Moors * @since 2.8.1 diff --git a/src/library/scala/annotation/migration.scala b/src/library/scala/annotation/migration.scala index adb6de6afd..e71be00f32 100644 --- a/src/library/scala/annotation/migration.scala +++ b/src/library/scala/annotation/migration.scala @@ -17,7 +17,7 @@ package scala.annotation * order between Scala 2.7 and 2.8. * * @param message A message describing the change, which is emitted - * by the compiler if the flag `-Xmigration` indicates a version + * by the compiler if the flag `-Xmigration` indicates a version * prior to the changedIn version. * * @param changedIn The version, in which the behaviour change was @@ -25,7 +25,4 @@ package scala.annotation * * @since 2.8 */ - private[scala] final class migration(message: String, changedIn: String) extends scala.annotation.StaticAnnotation { - @deprecated("Use the constructor taking two Strings instead.", "2.10.0") - def this(majorVersion: Int, minorVersion: Int, message: String) = this(message, majorVersion + "." + minorVersion) - } + private[scala] final class migration(message: String, changedIn: String) extends scala.annotation.StaticAnnotation diff --git a/src/library/scala/annotation/serializable.scala b/src/library/scala/annotation/serializable.scala deleted file mode 100644 index 1e1aff19d3..0000000000 --- a/src/library/scala/annotation/serializable.scala +++ /dev/null @@ -1,15 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala.annotation - -/** - * An annotation that designates the class to which it is applied as serializable - */ -@deprecated("instead of `@serializable class C`, use `class C extends Serializable`", "2.9.0") -class serializable extends scala.annotation.StaticAnnotation diff --git a/src/library/scala/annotation/target/package.scala b/src/library/scala/annotation/target/package.scala deleted file mode 100644 index ac2836c0a8..0000000000 --- a/src/library/scala/annotation/target/package.scala +++ /dev/null @@ -1,29 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala.annotation - -package object target { - @deprecated("Use `@scala.annotation.meta.beanGetter` instead", "2.10.0") - type beanGetter = scala.annotation.meta.beanGetter - - @deprecated("Use `@scala.annotation.meta.beanSetter` instead", "2.10.0") - type beanSetter = scala.annotation.meta.beanSetter - - @deprecated("Use `@scala.annotation.meta.field` instead", "2.10.0") - type field = scala.annotation.meta.field - - @deprecated("Use `@scala.annotation.meta.getter` instead", "2.10.0") - type getter = scala.annotation.meta.getter - - @deprecated("Use `@scala.annotation.meta.param` instead", "2.10.0") - type param = scala.annotation.meta.param - - @deprecated("Use `@scala.annotation.meta.setter` instead", "2.10.0") - type setter = scala.annotation.meta.setter -} diff --git a/src/library/scala/beans/ScalaBeanInfo.scala b/src/library/scala/beans/ScalaBeanInfo.scala index 3a95335d71..ac8fa263d7 100644 --- a/src/library/scala/beans/ScalaBeanInfo.scala +++ b/src/library/scala/beans/ScalaBeanInfo.scala @@ -27,7 +27,7 @@ abstract class ScalaBeanInfo(clazz: java.lang.Class[_], for (m <- clazz.getMethods if methods.exists(_ == m.getName)) yield new MethodDescriptor(m) - init + init() override def getPropertyDescriptors() = pd override def getMethodDescriptors() = md @@ -35,10 +35,10 @@ abstract class ScalaBeanInfo(clazz: java.lang.Class[_], // override def getAdditionalBeanInfo() = Array(Introspector getBeanInfo clazz.getSuperclass) private def init() { - var i = 0; + var i = 0 while (i < props.length) { pd(i/3) = new PropertyDescriptor(props(i), clazz, props(i+1), props(i+2)) - i = i + 3; + i = i + 3 } } diff --git a/src/library/scala/collection/BitSet.scala b/src/library/scala/collection/BitSet.scala index 6985563da2..e255e96140 100644 --- a/src/library/scala/collection/BitSet.scala +++ b/src/library/scala/collection/BitSet.scala @@ -8,7 +8,8 @@ -package scala.collection +package scala +package collection import generic._ diff --git a/src/library/scala/collection/BitSetLike.scala b/src/library/scala/collection/BitSetLike.scala index 4a1c0beaa6..8a8af79151 100644 --- a/src/library/scala/collection/BitSetLike.scala +++ b/src/library/scala/collection/BitSetLike.scala @@ -8,10 +8,10 @@ -package scala.collection +package scala +package collection import BitSetLike._ -import generic._ import mutable.StringBuilder /** A template trait for bitsets. @@ -70,6 +70,8 @@ trait BitSetLike[+This <: BitSetLike[This] with SortedSet[Int]] extends SortedSe s } + override def isEmpty: Boolean = 0 until nwords forall (i => word(i) == 0) + implicit def ordering: Ordering[Int] = Ordering.Int def rangeImpl(from: Option[Int], until: Option[Int]): This = { @@ -99,24 +101,35 @@ trait BitSetLike[+This <: BitSetLike[This] with SortedSet[Int]] extends SortedSe fromBitMaskNoCopy(a) } - def iterator: Iterator[Int] = new AbstractIterator[Int] { - private var current = 0 + def iterator: Iterator[Int] = iteratorFrom(0) + + override def keysIteratorFrom(start: Int) = new AbstractIterator[Int] { + private var current = start private val end = nwords * WordLength def hasNext: Boolean = { - while (current < end && !self.contains(current)) current += 1 - current < end + while (current != end && !self.contains(current)) current += 1 + current != end } def next(): Int = if (hasNext) { val r = current; current += 1; r } - else Iterator.empty.next + else Iterator.empty.next() } override def foreach[B](f: Int => B) { - for (i <- 0 until nwords) { - val w = word(i) - for (j <- i * WordLength until (i + 1) * WordLength) { - if ((w & (1L << j)) != 0L) f(j) + /* NOTE: while loops are significantly faster as of 2.11 and + one major use case of bitsets is performance. Also, there + is nothing to do when all bits are clear, so use that as + the inner loop condition. */ + var i = 0 + while (i < nwords) { + var w = word(i) + var j = i * WordLength + while (w != 0L) { + if ((w&1L) == 1L) f(j) + w = w >>> 1 + j += 1 } + i += 1 } } @@ -194,11 +207,15 @@ trait BitSetLike[+This <: BitSetLike[This] with SortedSet[Int]] extends SortedSe override def addString(sb: StringBuilder, start: String, sep: String, end: String) = { sb append start var pre = "" - for (i <- 0 until nwords * WordLength) + val max = nwords * WordLength + var i = 0 + while(i != max) { if (contains(i)) { sb append pre append i pre = sep } + i += 1 + } sb append end } @@ -207,8 +224,10 @@ trait BitSetLike[+This <: BitSetLike[This] with SortedSet[Int]] extends SortedSe /** Companion object for BitSets. Contains private data only */ object BitSetLike { - private[collection] val LogWL = 6 - private val WordLength = 64 + /* Final vals can sometimes be inlined as constants (faster) */ + private[collection] final val LogWL = 6 + private final val WordLength = 64 + private[collection] final val MaxSize = (Int.MaxValue >> LogWL) + 1 private[collection] def updateArray(elems: Array[Long], idx: Int, w: Long): Array[Long] = { var len = elems.length diff --git a/src/library/scala/collection/BufferedIterator.scala b/src/library/scala/collection/BufferedIterator.scala index 741bca4e46..e6e97d584c 100644 --- a/src/library/scala/collection/BufferedIterator.scala +++ b/src/library/scala/collection/BufferedIterator.scala @@ -8,7 +8,8 @@ -package scala.collection +package scala +package collection /** Buffered iterators are iterators which provide a method `head` * that inspects the next element without discarding it. diff --git a/src/library/scala/collection/CustomParallelizable.scala b/src/library/scala/collection/CustomParallelizable.scala index 53fe32b89f..cbeb28d643 100644 --- a/src/library/scala/collection/CustomParallelizable.scala +++ b/src/library/scala/collection/CustomParallelizable.scala @@ -6,7 +6,8 @@ ** |/ ** \* */ -package scala.collection +package scala +package collection import parallel.Combiner diff --git a/src/library/scala/collection/DefaultMap.scala b/src/library/scala/collection/DefaultMap.scala index 5c91183891..8afda7cfcf 100644 --- a/src/library/scala/collection/DefaultMap.scala +++ b/src/library/scala/collection/DefaultMap.scala @@ -6,11 +6,8 @@ ** |/ ** \* */ - - -package scala.collection - -import generic._ +package scala +package collection /** A default map which implements the `+` and `-` methods of maps. * @@ -27,14 +24,14 @@ import generic._ * @since 2.8 */ trait DefaultMap[A, +B] extends Map[A, B] { self => - + /** A default implementation which creates a new immutable map. */ override def +[B1 >: B](kv: (A, B1)): Map[A, B1] = { val b = Map.newBuilder[A, B1] b ++= this b += ((kv._1, kv._2)) - b.result + b.result() } /** A default implementation which creates a new immutable map. @@ -42,6 +39,6 @@ trait DefaultMap[A, +B] extends Map[A, B] { self => override def - (key: A): Map[A, B] = { val b = newBuilder b ++= this filter (key != _._1) - b.result + b.result() } } diff --git a/src/library/scala/collection/GenIterable.scala b/src/library/scala/collection/GenIterable.scala index b4e7a14ade..6fd4158726 100644 --- a/src/library/scala/collection/GenIterable.scala +++ b/src/library/scala/collection/GenIterable.scala @@ -6,7 +6,8 @@ ** |/ ** \* */ -package scala.collection +package scala +package collection import generic._ diff --git a/src/library/scala/collection/GenIterableLike.scala b/src/library/scala/collection/GenIterableLike.scala index 2ba9a7283d..1dbb54ddc7 100644 --- a/src/library/scala/collection/GenIterableLike.scala +++ b/src/library/scala/collection/GenIterableLike.scala @@ -6,9 +6,10 @@ ** |/ ** \* */ -package scala.collection +package scala +package collection -import generic.{ CanBuildFrom => CBF, _ } +import generic.{ CanBuildFrom => CBF } /** A template trait for all iterable collections which may possibly * have their operations implemented in parallel. diff --git a/src/library/scala/collection/GenIterableView.scala b/src/library/scala/collection/GenIterableView.scala deleted file mode 100644 index ca0332e9ad..0000000000 --- a/src/library/scala/collection/GenIterableView.scala +++ /dev/null @@ -1,18 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala.collection - - -import generic._ - - - -trait GenIterableView[+A, +Coll] extends GenIterableViewLike[A, Coll, GenIterableView[A, Coll]] { } - - diff --git a/src/library/scala/collection/GenIterableViewLike.scala b/src/library/scala/collection/GenIterableViewLike.scala deleted file mode 100644 index 4e4ceb4cea..0000000000 --- a/src/library/scala/collection/GenIterableViewLike.scala +++ /dev/null @@ -1,84 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala.collection - - - -import generic._ -import TraversableView.NoBuilder - - - -trait GenIterableViewLike[+A, - +Coll, - +This <: GenIterableView[A, Coll] with GenIterableViewLike[A, Coll, This]] -extends GenIterable[A] with GenIterableLike[A, This] with GenTraversableView[A, Coll] with GenTraversableViewLike[A, Coll, This] { -self => - - trait Transformed[+B] extends GenIterableView[B, Coll] with super.Transformed[B] { - def iterator: Iterator[B] - override def foreach[U](f: B => U): Unit = iterator foreach f - override def toString = viewToString - override def isEmpty = !iterator.hasNext - } - - trait EmptyView extends Transformed[Nothing] with super.EmptyView { - final def iterator: Iterator[Nothing] = Iterator.empty - } - - trait Forced[B] extends super.Forced[B] with Transformed[B] { - def iterator = forced.iterator - } - - trait Sliced extends super.Sliced with Transformed[A] { - def iterator: Iterator[A] = self.iterator.slice(from, until) - } - - trait Mapped[B] extends super.Mapped[B] with Transformed[B] { - def iterator = self.iterator map mapping - } - - trait FlatMapped[B] extends super.FlatMapped[B] with Transformed[B] { - def iterator: Iterator[B] = self.iterator flatMap mapping - } - - trait Appended[B >: A] extends super.Appended[B] with Transformed[B] { - def iterator = self.iterator ++ rest - } - - trait Filtered extends super.Filtered with Transformed[A] { - def iterator = self.iterator filter pred - } - - trait TakenWhile extends super.TakenWhile with Transformed[A] { - def iterator = self.iterator takeWhile pred - } - - trait DroppedWhile extends super.DroppedWhile with Transformed[A] { - def iterator = self.iterator dropWhile pred - } - - trait Zipped[B] extends Transformed[(A, B)] { - protected[this] val other: GenIterable[B] - def iterator: Iterator[(A, B)] = self.iterator zip other.iterator - final override protected[this] def viewIdentifier = "Z" - } - - trait ZippedAll[A1 >: A, B] extends Transformed[(A1, B)] { - protected[this] val other: GenIterable[B] - protected[this] val thisElem: A1 - protected[this] val thatElem: B - final override protected[this] def viewIdentifier = "Z" - def iterator: Iterator[(A1, B)] = - self.iterator.zipAll(other.iterator, thisElem, thatElem) - } - -} - - diff --git a/src/library/scala/collection/GenMap.scala b/src/library/scala/collection/GenMap.scala index f7b2ae4d70..d17a2de179 100644 --- a/src/library/scala/collection/GenMap.scala +++ b/src/library/scala/collection/GenMap.scala @@ -6,11 +6,11 @@ ** |/ ** \* */ -package scala.collection +package scala +package collection import generic._ - /** A trait for all traversable collections which may possibly * have their operations implemented in parallel. * @@ -27,12 +27,9 @@ extends GenMapLike[A, B, GenMap[A, B]] def updated [B1 >: B](key: A, value: B1): GenMap[A, B1] } - object GenMap extends GenMapFactory[GenMap] { def empty[A, B]: immutable.Map[A, B] = immutable.Map.empty /** $mapCanBuildFromInfo */ implicit def canBuildFrom[A, B]: CanBuildFrom[Coll, (A, B), GenMap[A, B]] = new MapCanBuildFrom[A, B] } - - diff --git a/src/library/scala/collection/GenMapLike.scala b/src/library/scala/collection/GenMapLike.scala index 367377a59c..4e7d359251 100644 --- a/src/library/scala/collection/GenMapLike.scala +++ b/src/library/scala/collection/GenMapLike.scala @@ -6,7 +6,8 @@ ** |/ ** \* */ -package scala.collection +package scala +package collection /** A trait for all maps upon which operations may be * implemented in parallel. diff --git a/src/library/scala/collection/GenSeq.scala b/src/library/scala/collection/GenSeq.scala index 4c5488d7e2..480562cab5 100644 --- a/src/library/scala/collection/GenSeq.scala +++ b/src/library/scala/collection/GenSeq.scala @@ -6,7 +6,8 @@ ** |/ ** \* */ -package scala.collection +package scala +package collection import generic._ diff --git a/src/library/scala/collection/GenSeqLike.scala b/src/library/scala/collection/GenSeqLike.scala index 78d63348c0..c3bad60072 100644 --- a/src/library/scala/collection/GenSeqLike.scala +++ b/src/library/scala/collection/GenSeqLike.scala @@ -6,7 +6,8 @@ ** |/ ** \* */ -package scala.collection +package scala +package collection import generic._ @@ -37,8 +38,8 @@ trait GenSeqLike[+A, +Repr] extends Any with GenIterableLike[A, Repr] with Equal * Example: * * {{{ - * scala> val x = LinkedList(1, 2, 3, 4, 5) - * x: scala.collection.mutable.LinkedList[Int] = LinkedList(1, 2, 3, 4, 5) + * scala> val x = List(1, 2, 3, 4, 5) + * x: List[Int] = List(1, 2, 3, 4, 5) * * scala> x(3) * res1: Int = 4 @@ -189,7 +190,7 @@ trait GenSeqLike[+A, +Repr] extends Any with GenIterableLike[A, Repr] with Equal */ def lastIndexWhere(p: A => Boolean, end: Int): Int - /** Returns new $coll wih elements in reversed order. + /** Returns new $coll with elements in reversed order. * * $willNotTerminateInf * @@ -301,14 +302,14 @@ trait GenSeqLike[+A, +Repr] extends Any with GenIterableLike[A, Repr] with Equal * * Example: * {{{ - * scala> val x = LinkedList(1) - * x: scala.collection.mutable.LinkedList[Int] = LinkedList(1) + * scala> val x = List(1) + * x: List[Int] = List(1) * * scala> val y = 2 +: x - * y: scala.collection.mutable.LinkedList[Int] = LinkedList(2, 1) + * y: List[Int] = List(2, 1) * * scala> println(x) - * LinkedList(1) + * List(1) * }}} * * @return a new $coll consisting of `elem` followed @@ -334,17 +335,14 @@ trait GenSeqLike[+A, +Repr] extends Any with GenIterableLike[A, Repr] with Equal * * Example: * {{{ - * scala> import scala.collection.mutable.LinkedList - * import scala.collection.mutable.LinkedList - * - * scala> val a = LinkedList(1) - * a: scala.collection.mutable.LinkedList[Int] = LinkedList(1) - * + * scala> val a = List(1) + * a: List[Int] = List(1) + * * scala> val b = a :+ 2 - * b: scala.collection.mutable.LinkedList[Int] = LinkedList(1, 2) - * + * b: List[Int] = List(1, 2) + * * scala> println(a) - * LinkedList(1) + * List(1) * }}} * * @return a new $coll consisting of diff --git a/src/library/scala/collection/GenSeqView.scala b/src/library/scala/collection/GenSeqView.scala deleted file mode 100644 index 92c8b779e9..0000000000 --- a/src/library/scala/collection/GenSeqView.scala +++ /dev/null @@ -1,18 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala.collection - - -import generic._ - - - -trait GenSeqView[+A, +Coll] extends GenSeqViewLike[A, Coll, GenSeqView[A, Coll]] { } - - diff --git a/src/library/scala/collection/GenSeqViewLike.scala b/src/library/scala/collection/GenSeqViewLike.scala deleted file mode 100644 index 51600218ad..0000000000 --- a/src/library/scala/collection/GenSeqViewLike.scala +++ /dev/null @@ -1,164 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala.collection - - - - -trait GenSeqViewLike[+A, - +Coll, - +This <: GenSeqView[A, Coll] with GenSeqViewLike[A, Coll, This]] -extends GenSeq[A] with GenSeqLike[A, This] with GenIterableView[A, Coll] with GenIterableViewLike[A, Coll, This] { -self => - - trait Transformed[+B] extends GenSeqView[B, Coll] with super.Transformed[B] { - def length: Int - def apply(idx: Int): B - override def toString = viewToString - } - - trait EmptyView extends Transformed[Nothing] with super.EmptyView { - final override def length = 0 - final override def apply(n: Int) = Nil(n) - } - - trait Forced[B] extends super.Forced[B] with Transformed[B] { - def length = forced.length - def apply(idx: Int) = forced.apply(idx) - } - - trait Sliced extends super.Sliced with Transformed[A] { - def length = iterator.size - def apply(idx: Int): A = - if (idx + from < until) self.apply(idx + from) - else throw new IndexOutOfBoundsException(idx.toString) - - override def foreach[U](f: A => U) = iterator foreach f - override def iterator: Iterator[A] = self.iterator drop from take endpoints.width - } - - trait Mapped[B] extends super.Mapped[B] with Transformed[B] { - def length = self.length - def apply(idx: Int): B = mapping(self(idx)) - } - - trait FlatMapped[B] extends super.FlatMapped[B] with Transformed[B] { - protected[this] lazy val index = { - val index = new Array[Int](self.length + 1) - index(0) = 0 - for (i <- 0 until self.length) // note that if the mapping returns a list, performance is bad, bad - index(i + 1) = index(i) + mapping(self(i)).seq.size - index - } - protected[this] def findRow(idx: Int, lo: Int, hi: Int): Int = { - val mid = (lo + hi) / 2 - if (idx < index(mid)) findRow(idx, lo, mid - 1) - else if (idx >= index(mid + 1)) findRow(idx, mid + 1, hi) - else mid - } - def length = index(self.length) - def apply(idx: Int) = { - val row = findRow(idx, 0, self.length - 1) - mapping(self(row)).seq.toSeq(idx - index(row)) - } - } - - trait Appended[B >: A] extends super.Appended[B] with Transformed[B] { - protected[this] lazy val restSeq = rest.toSeq - def length = self.length + restSeq.length - def apply(idx: Int) = - if (idx < self.length) self(idx) else restSeq(idx - self.length) - } - - trait Filtered extends super.Filtered with Transformed[A] { - protected[this] lazy val index = { - var len = 0 - val arr = new Array[Int](self.length) - for (i <- 0 until self.length) - if (pred(self(i))) { - arr(len) = i - len += 1 - } - arr take len - } - def length = index.length - def apply(idx: Int) = self(index(idx)) - } - - trait TakenWhile extends super.TakenWhile with Transformed[A] { - protected[this] lazy val len = self prefixLength pred - def length = len - def apply(idx: Int) = - if (idx < len) self(idx) - else throw new IndexOutOfBoundsException(idx.toString) - } - - trait DroppedWhile extends super.DroppedWhile with Transformed[A] { - protected[this] lazy val start = self prefixLength pred - def length = self.length - start - def apply(idx: Int) = - if (idx >= 0) self(idx + start) - else throw new IndexOutOfBoundsException(idx.toString) - } - - trait Zipped[B] extends super.Zipped[B] with Transformed[(A, B)] { - protected[this] lazy val thatSeq = other.seq.toSeq - /* Have to be careful here - other may be an infinite sequence. */ - def length = if ((thatSeq lengthCompare self.length) <= 0) thatSeq.length else self.length - def apply(idx: Int) = (self.apply(idx), thatSeq.apply(idx)) - } - - trait ZippedAll[A1 >: A, B] extends super.ZippedAll[A1, B] with Transformed[(A1, B)] { - protected[this] lazy val thatSeq = other.seq.toSeq - def length: Int = self.length max thatSeq.length - def apply(idx: Int) = - (if (idx < self.length) self.apply(idx) else thisElem, - if (idx < thatSeq.length) thatSeq.apply(idx) else thatElem) - } - - trait Reversed extends Transformed[A] { - override def iterator: Iterator[A] = createReversedIterator - def length: Int = self.length - def apply(idx: Int): A = self.apply(length - 1 - idx) - final override protected[this] def viewIdentifier = "R" - - private def createReversedIterator = { - var lst = List[A]() - for (elem <- self) lst ::= elem - lst.iterator - } - } - - trait Patched[B >: A] extends Transformed[B] { - protected[this] val from: Int - protected[this] val patch: GenSeq[B] - protected[this] val replaced: Int - private lazy val plen = patch.length - override def iterator: Iterator[B] = self.iterator patch (from, patch.iterator, replaced) - def length: Int = self.length + plen - replaced - def apply(idx: Int): B = - if (idx < from) self.apply(idx) - else if (idx < from + plen) patch.apply(idx - from) - else self.apply(idx - plen + replaced) - final override protected[this] def viewIdentifier = "P" - } - - trait Prepended[B >: A] extends Transformed[B] { - protected[this] val fst: B - override def iterator: Iterator[B] = Iterator.single(fst) ++ self.iterator - def length: Int = 1 + self.length - def apply(idx: Int): B = - if (idx == 0) fst - else self.apply(idx - 1) - final override protected[this] def viewIdentifier = "A" - } - -} - - diff --git a/src/library/scala/collection/GenSet.scala b/src/library/scala/collection/GenSet.scala index 832177b128..2467860095 100644 --- a/src/library/scala/collection/GenSet.scala +++ b/src/library/scala/collection/GenSet.scala @@ -7,7 +7,8 @@ \* */ -package scala.collection +package scala +package collection import generic._ diff --git a/src/library/scala/collection/GenSetLike.scala b/src/library/scala/collection/GenSetLike.scala index f22a7c8f09..c5355e58ec 100644 --- a/src/library/scala/collection/GenSetLike.scala +++ b/src/library/scala/collection/GenSetLike.scala @@ -6,7 +6,8 @@ ** |/ ** \* */ -package scala.collection +package scala +package collection /** A template trait for sets which may possibly diff --git a/src/library/scala/collection/GenTraversable.scala b/src/library/scala/collection/GenTraversable.scala index 3db2dd77a9..8705965992 100644 --- a/src/library/scala/collection/GenTraversable.scala +++ b/src/library/scala/collection/GenTraversable.scala @@ -6,14 +6,11 @@ ** |/ ** \* */ - - -package scala.collection - +package scala +package collection import generic._ - /** A trait for all traversable collections which may possibly * have their operations implemented in parallel. * @@ -30,10 +27,7 @@ extends GenTraversableLike[A, GenTraversable[A]] def companion: GenericCompanion[GenTraversable] = GenTraversable } - object GenTraversable extends GenTraversableFactory[GenTraversable] { implicit def canBuildFrom[A] = ReusableCBF.asInstanceOf[GenericCanBuildFrom[A]] def newBuilder[A] = Traversable.newBuilder } - - diff --git a/src/library/scala/collection/GenTraversableLike.scala b/src/library/scala/collection/GenTraversableLike.scala index 46134c921e..ca098e57b9 100644 --- a/src/library/scala/collection/GenTraversableLike.scala +++ b/src/library/scala/collection/GenTraversableLike.scala @@ -6,7 +6,8 @@ ** |/ ** \* */ -package scala.collection +package scala +package collection import generic._ @@ -238,7 +239,7 @@ trait GenTraversableLike[+A, +Repr] extends Any with GenTraversableOnce[A] with * // lettersOf will return a Set[Char], not a Seq * def lettersOf(words: Seq[String]) = words.toSet flatMap (word => word.toSeq) * - * // xs will be a an Iterable[Int] + * // xs will be an Iterable[Int] * val xs = Map("a" -> List(11,111), "b" -> List(22,222)).flatMap(_._2) * * // ys will be a Map[Int, Int] @@ -266,20 +267,20 @@ trait GenTraversableLike[+A, +Repr] extends Any with GenTraversableOnce[A] with * * Example: * {{{ - * scala> val a = LinkedList(1) - * a: scala.collection.mutable.LinkedList[Int] = LinkedList(1) - * - * scala> val b = LinkedList(2) - * b: scala.collection.mutable.LinkedList[Int] = LinkedList(2) - * + * scala> val a = List(1) + * a: List[Int] = List(1) + * + * scala> val b = List(2) + * b: List[Int] = List(2) + * * scala> val c = a ++ b - * c: scala.collection.mutable.LinkedList[Int] = LinkedList(1, 2) - * - * scala> val d = LinkedList('a') - * d: scala.collection.mutable.LinkedList[Char] = LinkedList(a) - * + * c: List[Int] = List(1, 2) + * + * scala> val d = List('a') + * d: List[Char] = List(a) + * * scala> val e = c ++ d - * e: scala.collection.mutable.LinkedList[AnyVal] = LinkedList(1, 2, a) + * e: List[AnyVal] = List(1, 2, a) * }}} * * @return a new $coll which contains all elements of this $coll @@ -323,7 +324,7 @@ trait GenTraversableLike[+A, +Repr] extends Any with GenTraversableOnce[A] with * @tparam K the type of keys returned by the discriminator function. * @return A map from keys to ${coll}s such that the following invariant holds: * {{{ - * (xs partition f)(k) = xs filter (x => f(x) == k) + * (xs groupBy f)(k) = xs filter (x => f(x) == k) * }}} * That is, every key `k` is bound to a $coll of those elements `x` * for which `f(x)` equals `k`. diff --git a/src/library/scala/collection/GenTraversableOnce.scala b/src/library/scala/collection/GenTraversableOnce.scala index 093db2a972..0cd91409cf 100644 --- a/src/library/scala/collection/GenTraversableOnce.scala +++ b/src/library/scala/collection/GenTraversableOnce.scala @@ -6,7 +6,8 @@ ** |/ ** \* */ -package scala.collection +package scala +package collection import scala.reflect.ClassTag import scala.collection.generic.CanBuildFrom @@ -119,19 +120,6 @@ trait GenTraversableOnce[+A] extends Any { */ def fold[A1 >: A](z: A1)(op: (A1, A1) => A1): A1 - /** A syntactic sugar for out of order folding. See `fold`. - * - * Example: - * {{{ - * scala> val a = LinkedList(1,2,3,4) - * a: scala.collection.mutable.LinkedList[Int] = LinkedList(1, 2, 3, 4) - * - * scala> val b = (a /:\ 5)(_+_) - * b: Int = 15 - * }}}*/ - @deprecated("use fold instead", "2.10.0") - def /:\[A1 >: A](z: A1)(op: (A1, A1) => A1): A1 = fold(z)(op) - /** Applies a binary operator to a start value and all elements of this $coll, * going left to right. * @@ -142,8 +130,8 @@ trait GenTraversableOnce[+A] extends Any { * * Note that the folding function used to compute b is equivalent to that used to compute c. * {{{ - * scala> val a = LinkedList(1,2,3,4) - * a: scala.collection.mutable.LinkedList[Int] = LinkedList(1, 2, 3, 4) + * scala> val a = List(1,2,3,4) + * a: List[Int] = List(1, 2, 3, 4) * * scala> val b = (5 /: a)(_+_) * b: Int = 15 @@ -179,8 +167,8 @@ trait GenTraversableOnce[+A] extends Any { * * Note that the folding function used to compute b is equivalent to that used to compute c. * {{{ - * scala> val a = LinkedList(1,2,3,4) - * a: scala.collection.mutable.LinkedList[Int] = LinkedList(1, 2, 3, 4) + * scala> val a = List(1,2,3,4) + * a: List[Int] = List(1, 2, 3, 4) * * scala> val b = (a :\ 5)(_+_) * b: Int = 15 @@ -261,11 +249,12 @@ trait GenTraversableOnce[+A] extends Any { * @tparam B the type of accumulated results * @param z the initial value for the accumulated result of the partition - this * will typically be the neutral element for the `seqop` operator (e.g. - * `Nil` for list concatenation or `0` for summation) + * `Nil` for list concatenation or `0` for summation) and may be evaluated + * more than once * @param seqop an operator used to accumulate results within a partition * @param combop an associative operator used to combine results from different partitions */ - def aggregate[B](z: B)(seqop: (B, A) => B, combop: (B, B) => B): B + def aggregate[B](z: =>B)(seqop: (B, A) => B, combop: (B, B) => B): B /** Applies a binary operator to all elements of this $coll, going right to left. * $willNotTerminateInf @@ -352,7 +341,7 @@ trait GenTraversableOnce[+A] extends Any { * * @param ord An ordering to be used for comparing elements. * @tparam A1 The type over which the ordering is defined. - * @return the smallest element of this $coll with respect to the ordering `cmp`. + * @return the smallest element of this $coll with respect to the ordering `ord`. * * @usecase def min: A * @inheritdoc @@ -365,7 +354,7 @@ trait GenTraversableOnce[+A] extends Any { * * @param ord An ordering to be used for comparing elements. * @tparam A1 The type over which the ordering is defined. - * @return the largest element of this $coll with respect to the ordering `cmp`. + * @return the largest element of this $coll with respect to the ordering `ord`. * * @usecase def max: A * @inheritdoc @@ -374,8 +363,34 @@ trait GenTraversableOnce[+A] extends Any { */ def max[A1 >: A](implicit ord: Ordering[A1]): A + /** Finds the first element which yields the largest value measured by function f. + * + * @param cmp An ordering to be used for comparing elements. + * @tparam B The result type of the function f. + * @param f The measuring function. + * @return the first element of this $coll with the largest value measured by function f + * with respect to the ordering `cmp`. + * + * @usecase def maxBy[B](f: A => B): A + * @inheritdoc + * + * @return the first element of this $coll with the largest value measured by function f. + */ def maxBy[B](f: A => B)(implicit cmp: Ordering[B]): A + /** Finds the first element which yields the smallest value measured by function f. + * + * @param cmp An ordering to be used for comparing elements. + * @tparam B The result type of the function f. + * @param f The measuring function. + * @return the first element of this $coll with the smallest value measured by function f + * with respect to the ordering `cmp`. + * + * @usecase def minBy[B](f: A => B): A + * @inheritdoc + * + * @return the first element of this $coll with the smallest value measured by function f. + */ def minBy[B](f: A => B)(implicit cmp: Ordering[B]): A def forall(pred: A => Boolean): Boolean @@ -491,7 +506,6 @@ trait GenTraversableOnce[+A] extends Any { def toIndexedSeq: immutable.IndexedSeq[A] /** Converts this $coll to a stream. - * $willNotTerminateInf * @return a stream containing all elements of this $coll. */ def toStream: Stream[A] @@ -503,7 +517,7 @@ trait GenTraversableOnce[+A] extends Any { */ def toIterator: Iterator[A] - /** Converts this $coll to a mutable buffer. + /** Uses the contents of this $coll to create a new mutable buffer. * $willNotTerminateInf * @return a buffer containing all elements of this $coll. */ diff --git a/src/library/scala/collection/GenTraversableView.scala b/src/library/scala/collection/GenTraversableView.scala deleted file mode 100644 index cceb06882e..0000000000 --- a/src/library/scala/collection/GenTraversableView.scala +++ /dev/null @@ -1,18 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala.collection - - -import generic._ - - - -trait GenTraversableView[+A, +Coll] extends GenTraversableViewLike[A, Coll, GenTraversableView[A, Coll]] { } - - diff --git a/src/library/scala/collection/GenTraversableViewLike.scala b/src/library/scala/collection/GenTraversableViewLike.scala deleted file mode 100644 index 77fe0802bf..0000000000 --- a/src/library/scala/collection/GenTraversableViewLike.scala +++ /dev/null @@ -1,139 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala.collection - - -import generic._ -import mutable.{ Builder, ArrayBuffer } -import TraversableView.NoBuilder - - -trait GenTraversableViewLike[+A, - +Coll, - +This <: GenTraversableView[A, Coll] with GenTraversableViewLike[A, Coll, This]] -extends GenTraversable[A] with GenTraversableLike[A, This] { -self => - - def force[B >: A, That](implicit bf: CanBuildFrom[Coll, B, That]): That - - protected def underlying: Coll - protected[this] def viewIdentifier: String - protected[this] def viewIdString: String - def viewToString = stringPrefix + viewIdString + "(...)" - - /** The implementation base trait of this view. - * This trait and all its subtraits has to be re-implemented for each - * ViewLike class. - */ - trait Transformed[+B] extends GenTraversableView[B, Coll] { - def foreach[U](f: B => U): Unit - - lazy val underlying = self.underlying - final override protected[this] def viewIdString = self.viewIdString + viewIdentifier - override def stringPrefix = self.stringPrefix - override def toString = viewToString - } - - trait EmptyView extends Transformed[Nothing] { - final override def isEmpty = true - final override def foreach[U](f: Nothing => U): Unit = () - } - - /** A fall back which forces everything into a vector and then applies an operation - * on it. Used for those operations which do not naturally lend themselves to a view - */ - trait Forced[B] extends Transformed[B] { - protected[this] val forced: GenSeq[B] - def foreach[U](f: B => U) = forced foreach f - final override protected[this] def viewIdentifier = "C" - } - - trait Sliced extends Transformed[A] { - protected[this] val endpoints: SliceInterval - protected[this] def from = endpoints.from - protected[this] def until = endpoints.until - // protected def newSliced(_endpoints: SliceInterval): Transformed[A] = - // self.newSliced(endpoints.recalculate(_endpoints)) - - def foreach[U](f: A => U) { - var index = 0 - for (x <- self) { - if (from <= index) { - if (until <= index) return - f(x) - } - index += 1 - } - } - final override protected[this] def viewIdentifier = "S" - } - - trait Mapped[B] extends Transformed[B] { - protected[this] val mapping: A => B - def foreach[U](f: B => U) { - for (x <- self) - f(mapping(x)) - } - final override protected[this] def viewIdentifier = "M" - } - - trait FlatMapped[B] extends Transformed[B] { - protected[this] val mapping: A => GenTraversableOnce[B] - def foreach[U](f: B => U) { - for (x <- self) - for (y <- mapping(x).seq) - f(y) - } - final override protected[this] def viewIdentifier = "N" - } - - trait Appended[B >: A] extends Transformed[B] { - protected[this] val rest: GenTraversable[B] - def foreach[U](f: B => U) { - self foreach f - rest foreach f - } - final override protected[this] def viewIdentifier = "A" - } - - trait Filtered extends Transformed[A] { - protected[this] val pred: A => Boolean - def foreach[U](f: A => U) { - for (x <- self) - if (pred(x)) f(x) - } - final override protected[this] def viewIdentifier = "F" - } - - trait TakenWhile extends Transformed[A] { - protected[this] val pred: A => Boolean - def foreach[U](f: A => U) { - for (x <- self) { - if (!pred(x)) return - f(x) - } - } - final override protected[this] def viewIdentifier = "T" - } - - trait DroppedWhile extends Transformed[A] { - protected[this] val pred: A => Boolean - def foreach[U](f: A => U) { - var go = false - for (x <- self) { - if (!go && !pred(x)) go = true - if (go) f(x) - } - } - final override protected[this] def viewIdentifier = "D" - } - -} - - diff --git a/src/library/scala/collection/IndexedSeq.scala b/src/library/scala/collection/IndexedSeq.scala index 2de0043c96..1a33026101 100644 --- a/src/library/scala/collection/IndexedSeq.scala +++ b/src/library/scala/collection/IndexedSeq.scala @@ -6,9 +6,8 @@ ** |/ ** \* */ - - -package scala.collection +package scala +package collection import generic._ import mutable.Builder @@ -28,14 +27,13 @@ trait IndexedSeq[+A] extends Seq[A] * @define coll indexed sequence * @define Coll `IndexedSeq` */ -object IndexedSeq extends SeqFactory[IndexedSeq] { +object IndexedSeq extends IndexedSeqFactory[IndexedSeq] { // A single CBF which can be checked against to identify // an indexed collection type. - override lazy val ReusableCBF: GenericCanBuildFrom[Nothing] = new GenericCanBuildFrom[Nothing] { + override val ReusableCBF: GenericCanBuildFrom[Nothing] = new GenericCanBuildFrom[Nothing] { override def apply() = newBuilder[Nothing] } def newBuilder[A]: Builder[A, IndexedSeq[A]] = immutable.IndexedSeq.newBuilder[A] implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, IndexedSeq[A]] = ReusableCBF.asInstanceOf[GenericCanBuildFrom[A]] } - diff --git a/src/library/scala/collection/IndexedSeqLike.scala b/src/library/scala/collection/IndexedSeqLike.scala index 9d0e9cbaea..18c9175ee1 100644 --- a/src/library/scala/collection/IndexedSeqLike.scala +++ b/src/library/scala/collection/IndexedSeqLike.scala @@ -6,9 +6,9 @@ ** |/ ** \* */ -package scala.collection +package scala +package collection -import generic._ import mutable.ArrayBuffer import scala.annotation.tailrec @@ -53,7 +53,6 @@ trait IndexedSeqLike[+A, +Repr] extends Any with SeqLike[A, Repr] { // pre: start >= 0, end <= self.length @SerialVersionUID(1756321872811029277L) protected class Elements(start: Int, end: Int) extends AbstractIterator[A] with BufferedIterator[A] with Serializable { - private def initialSize = if (end <= start) 0 else end - start private var index = start private def available = (end - index) max 0 @@ -61,7 +60,7 @@ trait IndexedSeqLike[+A, +Repr] extends Any with SeqLike[A, Repr] { def next(): A = { if (index >= end) - Iterator.empty.next + Iterator.empty.next() val x = self(index) index += 1 @@ -70,7 +69,7 @@ trait IndexedSeqLike[+A, +Repr] extends Any with SeqLike[A, Repr] { def head = { if (index >= end) - Iterator.empty.next + Iterator.empty.next() self(index) } diff --git a/src/library/scala/collection/IndexedSeqOptimized.scala b/src/library/scala/collection/IndexedSeqOptimized.scala index 09c4b14ba0..ade04e4de8 100755 --- a/src/library/scala/collection/IndexedSeqOptimized.scala +++ b/src/library/scala/collection/IndexedSeqOptimized.scala @@ -33,11 +33,17 @@ trait IndexedSeqOptimized[+A, +Repr] extends Any with IndexedSeqLike[A, Repr] { while (i < len) { f(this(i)); i += 1 } } + private def prefixLengthImpl(p: A => Boolean, expectTrue: Boolean): Int = { + var i = 0 + while (i < length && p(apply(i)) == expectTrue) i += 1 + i + } + override /*IterableLike*/ - def forall(p: A => Boolean): Boolean = prefixLength(p(_)) == length + def forall(p: A => Boolean): Boolean = prefixLengthImpl(p, expectTrue = true) == length override /*IterableLike*/ - def exists(p: A => Boolean): Boolean = prefixLength(!p(_)) != length + def exists(p: A => Boolean): Boolean = prefixLengthImpl(p, expectTrue = false) != length override /*IterableLike*/ def find(p: A => Boolean): Option[A] = { @@ -82,7 +88,7 @@ trait IndexedSeqOptimized[+A, +Repr] extends Any with IndexedSeqLike[A, Repr] { b += ((this(i), that(i).asInstanceOf[B])) i += 1 } - b.result + b.result() case _ => super.zip[A1, B, That](that)(bf) } @@ -97,7 +103,7 @@ trait IndexedSeqOptimized[+A, +Repr] extends Any with IndexedSeqLike[A, Repr] { b += ((this(i), i)) i += 1 } - b.result + b.result() } override /*IterableLike*/ @@ -113,7 +119,7 @@ trait IndexedSeqOptimized[+A, +Repr] extends Any with IndexedSeqLike[A, Repr] { b += self(i) i += 1 } - b.result + b.result() } override /*IterableLike*/ @@ -214,7 +220,7 @@ trait IndexedSeqOptimized[+A, +Repr] extends Any with IndexedSeqLike[A, Repr] { i -= 1 b += this(i) } - b.result + b.result() } override /*SeqLike*/ @@ -225,7 +231,7 @@ trait IndexedSeqOptimized[+A, +Repr] extends Any with IndexedSeqLike[A, Repr] { if (0 < i) { i -= 1 self(i) - } else Iterator.empty.next + } else Iterator.empty.next() } override /*SeqLike*/ diff --git a/src/library/scala/collection/Iterable.scala b/src/library/scala/collection/Iterable.scala index 5b73d720a8..a5ab8efd5c 100644 --- a/src/library/scala/collection/Iterable.scala +++ b/src/library/scala/collection/Iterable.scala @@ -8,10 +8,10 @@ -package scala.collection +package scala +package collection import generic._ -import scala.util.control.Breaks._ import mutable.Builder /** A base trait for iterable collections. @@ -51,4 +51,4 @@ object Iterable extends TraversableFactory[Iterable] { } /** Explicit instantiation of the `Iterable` trait to reduce class file size in subclasses. */ -private[scala] abstract class AbstractIterable[+A] extends AbstractTraversable[A] with Iterable[A] +abstract class AbstractIterable[+A] extends AbstractTraversable[A] with Iterable[A] diff --git a/src/library/scala/collection/IterableLike.scala b/src/library/scala/collection/IterableLike.scala index 540bd84b79..91ab1f6ac2 100644 --- a/src/library/scala/collection/IterableLike.scala +++ b/src/library/scala/collection/IterableLike.scala @@ -83,18 +83,34 @@ self => iterator.foldRight(z)(op) override /*TraversableLike*/ def reduceRight[B >: A](op: (A, B) => B): B = iterator.reduceRight(op) + + + /** Returns this $coll as an iterable collection. + * + * A new collection will not be built; lazy collections will stay lazy. + * + * $willNotTerminateInf + * @return an `Iterable` containing all elements of this $coll. + */ override /*TraversableLike*/ def toIterable: Iterable[A] = thisCollection - override /*TraversableLike*/ def toIterator: Iterator[A] = - iterator + + /** Returns an Iterator over the elements in this $coll. Produces the same + * result as `iterator`. + * $willNotTerminateInf + * @return an Iterator containing all elements of this $coll. + */ + @deprecatedOverriding("toIterator should stay consistent with iterator for all Iterables: override iterator instead.", "2.11.0") + override def toIterator: Iterator[A] = iterator + override /*TraversableLike*/ def head: A = - iterator.next + iterator.next() override /*TraversableLike*/ def slice(from: Int, until: Int): Repr = { val lo = math.max(from, 0) val elems = until - lo val b = newBuilder - if (elems <= 0) b.result + if (elems <= 0) b.result() else { b.sizeHintBounded(elems, this) var i = 0 @@ -103,14 +119,14 @@ self => b += it.next i += 1 } - b.result + b.result() } } override /*TraversableLike*/ def take(n: Int): Repr = { val b = newBuilder - if (n <= 0) b.result + if (n <= 0) b.result() else { b.sizeHintBounded(n, this) var i = 0 @@ -119,7 +135,7 @@ self => b += it.next i += 1 } - b.result + b.result() } } @@ -130,21 +146,21 @@ self => var i = 0 val it = iterator while (i < n && it.hasNext) { - it.next + it.next() i += 1 } - (b ++= it).result + (b ++= it).result() } override /*TraversableLike*/ def takeWhile(p: A => Boolean): Repr = { val b = newBuilder val it = iterator while (it.hasNext) { - val x = it.next - if (!p(x)) return b.result + val x = it.next() + if (!p(x)) return b.result() b += x } - b.result + b.result() } /** Partitions elements in fixed size ${coll}s. @@ -152,13 +168,13 @@ self => * * @param size the number of elements per group * @return An iterator producing ${coll}s of size `size`, except the - * last will be truncated if the elements don't divide evenly. + * last will be less than size `size` if the elements don't divide evenly. */ def grouped(size: Int): Iterator[Repr] = for (xs <- iterator grouped size) yield { val b = newBuilder b ++= xs - b.result + b.result() } /** Groups elements in fixed size blocks by passing a "sliding window" @@ -171,7 +187,7 @@ self => * fewer elements than size. */ def sliding(size: Int): Iterator[Repr] = sliding(size, 1) - + /** Groups elements in fixed size blocks by passing a "sliding window" * over them (as opposed to partitioning them, as is done in grouped.) * @see [[scala.collection.Iterator]], method `sliding` @@ -187,7 +203,7 @@ self => for (xs <- iterator.sliding(size, step)) yield { val b = newBuilder b ++= xs - b.result + b.result() } /** Selects last ''n'' elements. @@ -202,12 +218,12 @@ self => b.sizeHintBounded(n, this) val lead = this.iterator drop n var go = false - for (x <- this.seq) { - if (lead.hasNext) lead.next + for (x <- this) { + if (lead.hasNext) lead.next() else go = true if (go) b += x } - b.result + b.result() } /** Selects all elements except last ''n'' ones. @@ -224,9 +240,9 @@ self => val it = iterator while (lead.hasNext) { b += it.next - lead.next + lead.next() } - b.result + b.result() } override /*TraversableLike*/ def copyToArray[B >: A](xs: Array[B], start: Int, len: Int) { @@ -234,7 +250,7 @@ self => val end = (start + len) min xs.length val it = iterator while (i < end && it.hasNext) { - xs(i) = it.next + xs(i) = it.next() i += 1 } } @@ -244,8 +260,8 @@ self => val these = this.iterator val those = that.iterator while (these.hasNext && those.hasNext) - b += ((these.next, those.next)) - b.result + b += ((these.next(), those.next())) + b.result() } def zipAll[B, A1 >: A, That](that: GenIterable[B], thisElem: A1, thatElem: B)(implicit bf: CanBuildFrom[Repr, (A1, B), That]): That = { @@ -253,12 +269,12 @@ self => val these = this.iterator val those = that.iterator while (these.hasNext && those.hasNext) - b += ((these.next, those.next)) + b += ((these.next(), those.next())) while (these.hasNext) - b += ((these.next, thatElem)) + b += ((these.next(), thatElem)) while (those.hasNext) - b += ((thisElem, those.next)) - b.result + b += ((thisElem, those.next())) + b.result() } def zipWithIndex[A1 >: A, That](implicit bf: CanBuildFrom[Repr, (A1, Int), That]): That = { @@ -268,7 +284,7 @@ self => b += ((x, i)) i +=1 } - b.result + b.result() } def sameElements[B >: A](that: GenIterable[B]): Boolean = { diff --git a/src/library/scala/collection/IterableProxy.scala b/src/library/scala/collection/IterableProxy.scala index 2d041928cc..3a0e2ab115 100644 --- a/src/library/scala/collection/IterableProxy.scala +++ b/src/library/scala/collection/IterableProxy.scala @@ -6,9 +6,8 @@ ** |/ ** \* */ -package scala.collection - -import generic._ +package scala +package collection /** This trait implements a proxy for iterable objects. It forwards all calls * to a different iterable object. diff --git a/src/library/scala/collection/IterableProxyLike.scala b/src/library/scala/collection/IterableProxyLike.scala index 6968a54399..90e630ee28 100644 --- a/src/library/scala/collection/IterableProxyLike.scala +++ b/src/library/scala/collection/IterableProxyLike.scala @@ -8,7 +8,8 @@ -package scala.collection +package scala +package collection import generic._ import mutable.Buffer @@ -22,6 +23,7 @@ import mutable.Buffer * @version 2.8 * @since 2.8 */ +@deprecated("Proxying is deprecated due to lack of use and compiler-level support.", "2.11.0") trait IterableProxyLike[+A, +Repr <: IterableLike[A, Repr] with Iterable[A]] extends IterableLike[A, Repr] with TraversableProxyLike[A, Repr] { diff --git a/src/library/scala/collection/IterableView.scala b/src/library/scala/collection/IterableView.scala index 985556e0d4..b5f424d2ab 100644 --- a/src/library/scala/collection/IterableView.scala +++ b/src/library/scala/collection/IterableView.scala @@ -8,7 +8,8 @@ -package scala.collection +package scala +package collection import generic._ import TraversableView.NoBuilder @@ -16,7 +17,7 @@ import TraversableView.NoBuilder /** A base trait for non-strict views of `Iterable`s. * $iterableViewInfo */ -trait IterableView[+A, +Coll] extends IterableViewLike[A, Coll, IterableView[A, Coll]] with GenIterableView[A, Coll] +trait IterableView[+A, +Coll] extends IterableViewLike[A, Coll, IterableView[A, Coll]] /** An object containing the necessary implicit definitions to make * `IterableView`s work. Its definitions are generally not accessed directly by clients. diff --git a/src/library/scala/collection/IterableViewLike.scala b/src/library/scala/collection/IterableViewLike.scala index 3a81a3422f..668190f700 100644 --- a/src/library/scala/collection/IterableViewLike.scala +++ b/src/library/scala/collection/IterableViewLike.scala @@ -6,10 +6,10 @@ ** |/ ** \* */ -package scala.collection +package scala +package collection import generic._ -import TraversableView.NoBuilder import immutable.Stream import scala.language.implicitConversions @@ -34,39 +34,68 @@ trait IterableViewLike[+A, with IterableLike[A, This] with TraversableView[A, Coll] with TraversableViewLike[A, Coll, This] - with GenIterableViewLike[A, Coll, This] { self => - trait Transformed[+B] extends IterableView[B, Coll] with super[TraversableViewLike].Transformed[B] with super[GenIterableViewLike].Transformed[B] { + /** Explicit instantiation of the `Transformed` trait to reduce class file size in subclasses. */ + private[collection] abstract class AbstractTransformed[+B] extends Iterable[B] with super[TraversableViewLike].Transformed[B] with Transformed[B] + + trait Transformed[+B] extends IterableView[B, Coll] with super.Transformed[B] { def iterator: Iterator[B] override def foreach[U](f: B => U): Unit = iterator foreach f override def toString = viewToString + override def isEmpty = !iterator.hasNext } - /** Explicit instantiation of the `Transformed` trait to reduce class file size in subclasses. */ - private[collection] abstract class AbstractTransformed[+B] extends Iterable[B] with super[TraversableViewLike].Transformed[B] with Transformed[B] - - trait EmptyView extends Transformed[Nothing] with super[TraversableViewLike].EmptyView with super[GenIterableViewLike].EmptyView + trait EmptyView extends Transformed[Nothing] with super.EmptyView { + final def iterator: Iterator[Nothing] = Iterator.empty + } - trait Forced[B] extends super[TraversableViewLike].Forced[B] with super[GenIterableViewLike].Forced[B] with Transformed[B] + trait Forced[B] extends super.Forced[B] with Transformed[B] { + def iterator = forced.iterator + } - trait Sliced extends super[TraversableViewLike].Sliced with super[GenIterableViewLike].Sliced with Transformed[A] + trait Sliced extends super.Sliced with Transformed[A] { + def iterator: Iterator[A] = self.iterator.slice(from, until) + } - trait Mapped[B] extends super[TraversableViewLike].Mapped[B] with super[GenIterableViewLike].Mapped[B] with Transformed[B] + trait Mapped[B] extends super.Mapped[B] with Transformed[B] { + def iterator = self.iterator map mapping + } - trait FlatMapped[B] extends super[TraversableViewLike].FlatMapped[B] with super[GenIterableViewLike].FlatMapped[B] with Transformed[B] + trait FlatMapped[B] extends super.FlatMapped[B] with Transformed[B] { + def iterator: Iterator[B] = self.iterator flatMap mapping + } - trait Appended[B >: A] extends super[TraversableViewLike].Appended[B] with super[GenIterableViewLike].Appended[B] with Transformed[B] + trait Appended[B >: A] extends super.Appended[B] with Transformed[B] { + def iterator = self.iterator ++ rest + } - trait Filtered extends super[TraversableViewLike].Filtered with super[GenIterableViewLike].Filtered with Transformed[A] + trait Filtered extends super.Filtered with Transformed[A] { + def iterator = self.iterator filter pred + } - trait TakenWhile extends super[TraversableViewLike].TakenWhile with super[GenIterableViewLike].TakenWhile with Transformed[A] + trait TakenWhile extends super.TakenWhile with Transformed[A] { + def iterator = self.iterator takeWhile pred + } - trait DroppedWhile extends super[TraversableViewLike].DroppedWhile with super[GenIterableViewLike].DroppedWhile with Transformed[A] + trait DroppedWhile extends super.DroppedWhile with Transformed[A] { + def iterator = self.iterator dropWhile pred + } - trait Zipped[B] extends Transformed[(A, B)] with super[GenIterableViewLike].Zipped[B] + trait Zipped[B] extends Transformed[(A, B)] { + protected[this] val other: GenIterable[B] + def iterator: Iterator[(A, B)] = self.iterator zip other.iterator + final override protected[this] def viewIdentifier = "Z" + } - trait ZippedAll[A1 >: A, B] extends Transformed[(A1, B)] with super[GenIterableViewLike].ZippedAll[A1, B] + trait ZippedAll[A1 >: A, B] extends Transformed[(A1, B)] { + protected[this] val other: GenIterable[B] + protected[this] val thisElem: A1 + protected[this] val thatElem: B + final override protected[this] def viewIdentifier = "Z" + def iterator: Iterator[(A1, B)] = + self.iterator.zipAll(other.iterator, thisElem, thatElem) + } private[this] implicit def asThis(xs: Transformed[A]): This = xs.asInstanceOf[This] @@ -117,5 +146,14 @@ trait IterableViewLike[+A, override def sliding(size: Int, step: Int): Iterator[This] = self.iterator.sliding(size, step) map (x => newForced(x).asInstanceOf[This]) + override def sliding(size: Int): Iterator[This] = + sliding(size, 1) // we could inherit this, but that implies knowledge of the way the super class is implemented. + + override def dropRight(n: Int): This = + take(thisSeq.length - n) + + override def takeRight(n: Int): This = + drop(thisSeq.length - n) + override def stringPrefix = "IterableView" } diff --git a/src/library/scala/collection/Iterator.scala b/src/library/scala/collection/Iterator.scala index 2bb5bd1df9..f6f46e158f 100644 --- a/src/library/scala/collection/Iterator.scala +++ b/src/library/scala/collection/Iterator.scala @@ -161,6 +161,41 @@ object Iterator { def hasNext = true def next = elem } + + /** Avoid stack overflows when applying ++ to lots of iterators by + * flattening the unevaluated iterators out into a vector of closures. + */ + private[scala] final class ConcatIterator[+A](private[this] var current: Iterator[A], initial: Vector[() => Iterator[A]]) extends Iterator[A] { + @deprecated def this(initial: Vector[() => Iterator[A]]) = this(Iterator.empty, initial) // for binary compatibility + private[this] var queue: Vector[() => Iterator[A]] = initial + // Advance current to the next non-empty iterator + // current is set to null when all iterators are exhausted + private[this] def advance(): Boolean = { + if (queue.isEmpty) { + current = null + false + } + else { + current = queue.head() + queue = queue.tail + current.hasNext || advance() + } + } + def hasNext = (current ne null) && (current.hasNext || advance()) + def next() = if (hasNext) current.next else Iterator.empty.next + + override def ++[B >: A](that: => GenTraversableOnce[B]): Iterator[B] = + new ConcatIterator(current, queue :+ (() => that.toIterator)) + } + + private[scala] final class JoinIterator[+A](lhs: Iterator[A], that: => GenTraversableOnce[A]) extends Iterator[A] { + private[this] lazy val rhs: Iterator[A] = that.toIterator + def hasNext = lhs.hasNext || rhs.hasNext + def next = if (lhs.hasNext) lhs.next else rhs.next + + override def ++[B >: A](that: => GenTraversableOnce[B]) = + new ConcatIterator(this, Vector(() => that.toIterator)) + } } import Iterator.empty @@ -338,24 +373,7 @@ trait Iterator[+A] extends TraversableOnce[A] { * @usecase def ++(that: => Iterator[A]): Iterator[A] * @inheritdoc */ - def ++[B >: A](that: => GenTraversableOnce[B]): Iterator[B] = new AbstractIterator[B] { - // optimize a little bit to prevent n log n behavior. - private var cur : Iterator[B] = self - private var selfExhausted : Boolean = false - // since that is by-name, make sure it's only referenced once - - // if "val it = that" is inside the block, then hasNext on an empty - // iterator will continually reevaluate it. (ticket #3269) - lazy val it = that.toIterator - // the eq check is to avoid an infinite loop on "x ++ x" - def hasNext = cur.hasNext || (!selfExhausted && { - it.hasNext && { - cur = it - selfExhausted = true - true - } - }) - def next() = { hasNext; cur.next() } - } + def ++[B >: A](that: => GenTraversableOnce[B]): Iterator[B] = new Iterator.JoinIterator(self, that) /** Creates a new iterator by applying a function to all values produced by this iterator * and concatenating the results. @@ -368,7 +386,7 @@ trait Iterator[+A] extends TraversableOnce[A] { def flatMap[B](f: A => GenTraversableOnce[B]): Iterator[B] = new AbstractIterator[B] { private var cur: Iterator[B] = empty def hasNext: Boolean = - cur.hasNext || self.hasNext && { cur = f(self.next).toIterator; hasNext } + cur.hasNext || self.hasNext && { cur = f(self.next()).toIterator; hasNext } def next(): B = (if (hasNext) cur else empty).next() } @@ -408,7 +426,7 @@ trait Iterator[+A] extends TraversableOnce[A] { def corresponds[B](that: GenTraversableOnce[B])(p: (A, B) => Boolean): Boolean = { val that0 = that.toIterator while (hasNext && that0.hasNext) - if (!p(next, that0.next)) return false + if (!p(next(), that0.next())) return false hasNext == that0.hasNext } @@ -555,14 +573,13 @@ trait Iterator[+A] extends TraversableOnce[A] { def span(p: A => Boolean): (Iterator[A], Iterator[A]) = { val self = buffered - /** + /* * Giving a name to following iterator (as opposed to trailing) because * anonymous class is represented as a structural type that trailing * iterator is referring (the finish() method) and thus triggering * handling of structural calls. It's not what's intended here. */ class Leading extends AbstractIterator[A] { - private var isDone = false val lookahead = new mutable.Queue[A] def advance() = { self.hasNext && p(self.head) && { @@ -572,7 +589,6 @@ trait Iterator[+A] extends TraversableOnce[A] { } def finish() = { while (advance()) () - isDone = true } def hasNext = lookahead.nonEmpty || advance() def next() = { @@ -632,7 +648,7 @@ trait Iterator[+A] extends TraversableOnce[A] { */ def zip[B](that: Iterator[B]): Iterator[(A, B)] = new AbstractIterator[(A, B)] { def hasNext = self.hasNext && that.hasNext - def next = (self.next, that.next) + def next = (self.next(), that.next()) } /** Appends an element value to this iterator until a given target length is reached. @@ -652,9 +668,9 @@ trait Iterator[+A] extends TraversableOnce[A] { def hasNext = self.hasNext || count < len def next = { count += 1 - if (self.hasNext) self.next + if (self.hasNext) self.next() else if (count <= len) elem - else empty.next + else empty.next() } } @@ -669,7 +685,7 @@ trait Iterator[+A] extends TraversableOnce[A] { var idx = 0 def hasNext = self.hasNext def next = { - val ret = (self.next, idx) + val ret = (self.next(), idx) idx += 1 ret } @@ -906,11 +922,16 @@ trait Iterator[+A] extends TraversableOnce[A] { /** For reasons which remain to be determined, calling * self.take(n).toSeq cause an infinite loop, so we have * a slight variation on take for local usage. + * NB: self.take.toSeq is slice.toStream, lazily built on self, + * so a subsequent self.hasNext would not test self after the + * group was consumed. */ private def takeDestructively(size: Int): Seq[A] = { val buf = new ArrayBuffer[A] var i = 0 - while (self.hasNext && i < size) { + // The order of terms in the following condition is important + // here as self.hasNext could be blocking + while (i < size && self.hasNext) { buf += self.next i += 1 } @@ -927,12 +948,10 @@ trait Iterator[+A] extends TraversableOnce[A] { // so the rest of the code can be oblivious val xs: Seq[B] = { val res = takeDestructively(count) - // extra checks so we don't calculate length unless there's reason - if (pad.isDefined && !self.hasNext) { - val shortBy = count - res.length - if (shortBy > 0) res ++ padding(shortBy) else res - } - else res + // was: extra checks so we don't calculate length unless there's reason + // but since we took the group eagerly, just use the fast length + val shortBy = count - res.length + if (shortBy > 0 && pad.isDefined) res ++ padding(shortBy) else res } lazy val len = xs.length lazy val incomplete = len < count @@ -1054,12 +1073,12 @@ trait Iterator[+A] extends TraversableOnce[A] { val e = self.next() gap enqueue e e - } else gap.dequeue + } else gap.dequeue() } // to verify partnerhood we use reference equality on gap because // type testing does not discriminate based on origin. private def compareGap(queue: scala.collection.mutable.Queue[A]) = gap eq queue - override def hashCode = gap.hashCode + override def hashCode = gap.hashCode() override def equals(other: Any) = other match { case x: Partner => x.compareGap(gap) && gap.isEmpty case _ => super.equals(other) @@ -1118,6 +1137,7 @@ trait Iterator[+A] extends TraversableOnce[A] { xs(i) = next() i += 1 } + // TODO: return i - start so the caller knows how many values read? } /** Tests if another iterator produces the same values as this one. @@ -1140,7 +1160,7 @@ trait Iterator[+A] extends TraversableOnce[A] { def toTraversable: Traversable[A] = toStream def toIterator: Iterator[A] = self def toStream: Stream[A] = - if (self.hasNext) Stream.cons(self.next, self.toStream) + if (self.hasNext) Stream.cons(self.next(), self.toStream) else Stream.empty[A] @@ -1154,4 +1174,4 @@ trait Iterator[+A] extends TraversableOnce[A] { } /** Explicit instantiation of the `Iterator` trait to reduce class file size in subclasses. */ -private[scala] abstract class AbstractIterator[+A] extends Iterator[A] +abstract class AbstractIterator[+A] extends Iterator[A] diff --git a/src/library/scala/collection/JavaConversions.scala b/src/library/scala/collection/JavaConversions.scala index 59d4259c70..7bfa60771f 100644 --- a/src/library/scala/collection/JavaConversions.scala +++ b/src/library/scala/collection/JavaConversions.scala @@ -6,9 +6,9 @@ ** |/ ** \* */ -package scala.collection +package scala +package collection -import java.{ lang => jl, util => ju }, java.util.{ concurrent => juc } import convert._ /** A collection of implicit conversions supporting interoperability between @@ -22,7 +22,6 @@ import convert._ * scala.collection.mutable.Buffer <=> java.util.List * scala.collection.mutable.Set <=> java.util.Set * scala.collection.mutable.Map <=> java.util.{ Map, Dictionary } - * scala.collection.mutable.ConcurrentMap (deprecated since 2.10) <=> java.util.concurrent.ConcurrentMap * scala.collection.concurrent.Map <=> java.util.concurrent.ConcurrentMap *}}} * In all cases, converting from a source type to a target type and back @@ -50,83 +49,4 @@ import convert._ * @author Martin Odersky * @since 2.8 */ -object JavaConversions extends WrapAsScala with WrapAsJava { - @deprecated("Use a member of scala.collection.convert.Wrappers", "2.10.0") type ConcurrentMapWrapper[A, B] = Wrappers.ConcurrentMapWrapper[A, B] - @deprecated("Use a member of scala.collection.convert.Wrappers", "2.10.0") type DictionaryWrapper[A, B] = Wrappers.DictionaryWrapper[A, B] - @deprecated("Use a member of scala.collection.convert.Wrappers", "2.10.0") type IterableWrapper[A] = Wrappers.IterableWrapper[A] - @deprecated("Use a member of scala.collection.convert.Wrappers", "2.10.0") type IteratorWrapper[A] = Wrappers.IteratorWrapper[A] - @deprecated("Use a member of scala.collection.convert.Wrappers", "2.10.0") type JCollectionWrapper[A] = Wrappers.JCollectionWrapper[A] - @deprecated("Use a member of scala.collection.convert.Wrappers", "2.10.0") type JConcurrentMapWrapper[A, B] = Wrappers.JConcurrentMapWrapper[A, B] - @deprecated("Use a member of scala.collection.convert.Wrappers", "2.10.0") type JDictionaryWrapper[A, B] = Wrappers.JDictionaryWrapper[A, B] - @deprecated("Use a member of scala.collection.convert.Wrappers", "2.10.0") type JEnumerationWrapper[A] = Wrappers.JEnumerationWrapper[A] - @deprecated("Use a member of scala.collection.convert.Wrappers", "2.10.0") type JIterableWrapper[A] = Wrappers.JIterableWrapper[A] - @deprecated("Use a member of scala.collection.convert.Wrappers", "2.10.0") type JIteratorWrapper[A] = Wrappers.JIteratorWrapper[A] - @deprecated("Use a member of scala.collection.convert.Wrappers", "2.10.0") type JListWrapper[A] = Wrappers.JListWrapper[A] - @deprecated("Use a member of scala.collection.convert.Wrappers", "2.10.0") type JMapWrapper[A, B] = Wrappers.JMapWrapper[A, B] - @deprecated("Use a member of scala.collection.convert.Wrappers", "2.10.0") type JPropertiesWrapper = Wrappers.JPropertiesWrapper - @deprecated("Use a member of scala.collection.convert.Wrappers", "2.10.0") type JSetWrapper[A] = Wrappers.JSetWrapper[A] - @deprecated("Use a member of scala.collection.convert.Wrappers", "2.10.0") type MapWrapper[A, B] = Wrappers.MapWrapper[A, B] - @deprecated("Use a member of scala.collection.convert.Wrappers", "2.10.0") type MutableBufferWrapper[A] = Wrappers.MutableBufferWrapper[A] - @deprecated("Use a member of scala.collection.convert.Wrappers", "2.10.0") type MutableMapWrapper[A, B] = Wrappers.MutableMapWrapper[A, B] - @deprecated("Use a member of scala.collection.convert.Wrappers", "2.10.0") type MutableSeqWrapper[A] = Wrappers.MutableSeqWrapper[A] - @deprecated("Use a member of scala.collection.convert.Wrappers", "2.10.0") type MutableSetWrapper[A] = Wrappers.MutableSetWrapper[A] - @deprecated("Use a member of scala.collection.convert.Wrappers", "2.10.0") type SeqWrapper[A] = Wrappers.SeqWrapper[A] - @deprecated("Use a member of scala.collection.convert.Wrappers", "2.10.0") type SetWrapper[A] = Wrappers.SetWrapper[A] - @deprecated("Use a member of scala.collection.convert.Wrappers", "2.10.0") type ToIteratorWrapper[A] = Wrappers.ToIteratorWrapper[A] - @deprecated("Use a member of scala.collection.convert.Wrappers", "2.10.0") val DictionaryWrapper = Wrappers.DictionaryWrapper - @deprecated("Use a member of scala.collection.convert.Wrappers", "2.10.0") val IterableWrapper = Wrappers.IterableWrapper - @deprecated("Use a member of scala.collection.convert.Wrappers", "2.10.0") val IteratorWrapper = Wrappers.IteratorWrapper - @deprecated("Use a member of scala.collection.convert.Wrappers", "2.10.0") val JCollectionWrapper = Wrappers.JCollectionWrapper - @deprecated("Use a member of scala.collection.convert.Wrappers", "2.10.0") val JConcurrentMapWrapper = Wrappers.JConcurrentMapWrapper - @deprecated("Use a member of scala.collection.convert.Wrappers", "2.10.0") val JDictionaryWrapper = Wrappers.JDictionaryWrapper - @deprecated("Use a member of scala.collection.convert.Wrappers", "2.10.0") val JEnumerationWrapper = Wrappers.JEnumerationWrapper - @deprecated("Use a member of scala.collection.convert.Wrappers", "2.10.0") val JIterableWrapper = Wrappers.JIterableWrapper - @deprecated("Use a member of scala.collection.convert.Wrappers", "2.10.0") val JIteratorWrapper = Wrappers.JIteratorWrapper - @deprecated("Use a member of scala.collection.convert.Wrappers", "2.10.0") val JListWrapper = Wrappers.JListWrapper - @deprecated("Use a member of scala.collection.convert.Wrappers", "2.10.0") val JMapWrapper = Wrappers.JMapWrapper - @deprecated("Use a member of scala.collection.convert.Wrappers", "2.10.0") val JPropertiesWrapper = Wrappers.JPropertiesWrapper - @deprecated("Use a member of scala.collection.convert.Wrappers", "2.10.0") val JSetWrapper = Wrappers.JSetWrapper - @deprecated("Use a member of scala.collection.convert.Wrappers", "2.10.0") val MutableBufferWrapper = Wrappers.MutableBufferWrapper - @deprecated("Use a member of scala.collection.convert.Wrappers", "2.10.0") val MutableMapWrapper = Wrappers.MutableMapWrapper - @deprecated("Use a member of scala.collection.convert.Wrappers", "2.10.0") val MutableSeqWrapper = Wrappers.MutableSeqWrapper - @deprecated("Use a member of scala.collection.convert.Wrappers", "2.10.0") val MutableSetWrapper = Wrappers.MutableSetWrapper - @deprecated("Use a member of scala.collection.convert.Wrappers", "2.10.0") val SeqWrapper = Wrappers.SeqWrapper - - // Note to implementors: the cavalcade of deprecated methods herein should - // serve as a warning to any who follow: don't overload implicit methods. - - @deprecated("use bufferAsJavaList instead", "2.9.0") - def asJavaList[A](b : mutable.Buffer[A]): ju.List[A] = bufferAsJavaList[A](b) - - @deprecated("use mutableSeqAsJavaList instead", "2.9.0") - def asJavaList[A](b : mutable.Seq[A]): ju.List[A] = mutableSeqAsJavaList[A](b) - - @deprecated("use seqAsJavaList instead", "2.9.0") - def asJavaList[A](b : Seq[A]): ju.List[A] = seqAsJavaList[A](b) - - @deprecated("use mutableSetAsJavaSet instead", "2.9.0") - def asJavaSet[A](s : mutable.Set[A]): ju.Set[A] = mutableSetAsJavaSet[A](s) - - @deprecated("use setAsJavaSet instead", "2.9.0") - def asJavaSet[A](s: Set[A]): ju.Set[A] = setAsJavaSet[A](s) - - @deprecated("use mutableMapAsJavaMap instead", "2.9.0") - def asJavaMap[A, B](m : mutable.Map[A, B]): ju.Map[A, B] = mutableMapAsJavaMap[A, B](m) - - @deprecated("use mapAsJavaMap instead", "2.9.0") - def asJavaMap[A, B](m : Map[A, B]): ju.Map[A, B] = mapAsJavaMap[A, B](m) - - @deprecated("use iterableAsScalaIterable instead", "2.9.0") - def asScalaIterable[A](i : jl.Iterable[A]): Iterable[A] = iterableAsScalaIterable[A](i) - - @deprecated("use collectionAsScalaIterable instead", "2.9.0") - def asScalaIterable[A](i : ju.Collection[A]): Iterable[A] = collectionAsScalaIterable[A](i) - - @deprecated("use mapAsScalaMap instead", "2.9.0") - def asScalaMap[A, B](m: ju.Map[A, B]): mutable.Map[A, B] = mapAsScalaMap[A, B](m) - - @deprecated("use propertiesAsScalaMap instead", "2.9.0") - def asScalaMap(p: ju.Properties): mutable.Map[String, String] = propertiesAsScalaMap(p) -} - - +object JavaConversions extends WrapAsScala with WrapAsJava diff --git a/src/library/scala/collection/JavaConverters.scala b/src/library/scala/collection/JavaConverters.scala index ab3ac8925c..a4fa58b13c 100755 --- a/src/library/scala/collection/JavaConverters.scala +++ b/src/library/scala/collection/JavaConverters.scala @@ -6,16 +6,15 @@ ** |/ ** \* */ -package scala.collection +package scala +package collection -import java.{ lang => jl, util => ju }, java.util.{ concurrent => juc } import convert._ // TODO: I cleaned all this documentation up in JavaConversions, but the // documentation in here is basically the pre-cleaned-up version with minor // additions. Would be nice to have in one place. - /** A collection of decorators that allow converting between * Scala and Java collections using `asScala` and `asJava` methods. * @@ -26,7 +25,7 @@ import convert._ * - `scala.collection.mutable.Buffer` <=> `java.util.List` * - `scala.collection.mutable.Set` <=> `java.util.Set` * - `scala.collection.mutable.Map` <=> `java.util.Map` - * - `scala.collection.mutable.ConcurrentMap` <=> `java.util.concurrent.ConcurrentMap` + * - `scala.collection.mutable.concurrent.Map` <=> `java.util.concurrent.ConcurrentMap` * * In all cases, converting from a source type to a target type and back * again will return the original source object, e.g. @@ -56,48 +55,4 @@ import convert._ * @author Martin Odersky * @since 2.8.1 */ -object JavaConverters extends DecorateAsJava with DecorateAsScala { - @deprecated("Don't access these decorators directly.", "2.10.0") - type AsJava[A] = Decorators.AsJava[A] - @deprecated("Don't access these decorators directly.", "2.10.0") - type AsScala[A] = Decorators.AsScala[A] - @deprecated("Don't access these decorators directly.", "2.10.0") - type AsJavaCollection[A] = Decorators.AsJavaCollection[A] - @deprecated("Don't access these decorators directly.", "2.10.0") - type AsJavaEnumeration[A] = Decorators.AsJavaEnumeration[A] - @deprecated("Don't access these decorators directly.", "2.10.0") - type AsJavaDictionary[A, B] = Decorators.AsJavaDictionary[A, B] - - @deprecated("Use bufferAsJavaListConverter instead", "2.9.0") - def asJavaListConverter[A](b : mutable.Buffer[A]): AsJava[ju.List[A]] = bufferAsJavaListConverter(b) - - @deprecated("Use mutableSeqAsJavaListConverter instead", "2.9.0") - def asJavaListConverter[A](b : mutable.Seq[A]): AsJava[ju.List[A]] = mutableSeqAsJavaListConverter(b) - - @deprecated("Use seqAsJavaListConverter instead", "2.9.0") - def asJavaListConverter[A](b : Seq[A]): AsJava[ju.List[A]] = seqAsJavaListConverter(b) - - @deprecated("Use mutableSetAsJavaSetConverter instead", "2.9.0") - def asJavaSetConverter[A](s : mutable.Set[A]): AsJava[ju.Set[A]] = mutableSetAsJavaSetConverter(s) - - @deprecated("Use setAsJavaSetConverter instead", "2.9.0") - def asJavaSetConverter[A](s : Set[A]): AsJava[ju.Set[A]] = setAsJavaSetConverter(s) - - @deprecated("use mutableMapAsJavaMapConverter instead", "2.9.0") - def asJavaMapConverter[A, B](m : mutable.Map[A, B]): AsJava[ju.Map[A, B]] = mutableMapAsJavaMapConverter(m) - - @deprecated("Use mapAsJavaMapConverter instead", "2.9.0") - def asJavaMapConverter[A, B](m : Map[A, B]): AsJava[ju.Map[A, B]] = mapAsJavaMapConverter(m) - - @deprecated("Use iterableAsScalaIterableConverter instead", "2.9.0") - def asScalaIterableConverter[A](i : jl.Iterable[A]): AsScala[Iterable[A]] = iterableAsScalaIterableConverter(i) - - @deprecated("Use collectionAsScalaIterableConverter instead", "2.9.0") - def asScalaIterableConverter[A](i : ju.Collection[A]): AsScala[Iterable[A]] = collectionAsScalaIterableConverter(i) - - @deprecated("Use mapAsScalaMapConverter instead", "2.9.0") - def asScalaMapConverter[A, B](m : ju.Map[A, B]): AsScala[mutable.Map[A, B]] = mapAsScalaMapConverter(m) - - @deprecated("Use propertiesAsScalaMapConverter instead", "2.9.0") - def asScalaMapConverter(p: ju.Properties): AsScala[mutable.Map[String, String]] = propertiesAsScalaMapConverter(p) -} +object JavaConverters extends DecorateAsJava with DecorateAsScala diff --git a/src/library/scala/collection/LinearSeq.scala b/src/library/scala/collection/LinearSeq.scala index e52a1936fe..49fbb902ab 100644 --- a/src/library/scala/collection/LinearSeq.scala +++ b/src/library/scala/collection/LinearSeq.scala @@ -8,7 +8,8 @@ -package scala.collection +package scala +package collection import generic._ import mutable.Builder @@ -24,7 +25,7 @@ trait LinearSeq[+A] extends Seq[A] } /** $factoryInfo - * The current default implementation of a $Coll is a `Vector`. + * The current default implementation of a $Coll is a `List`. * @define coll linear sequence * @define Coll `LinearSeq` */ diff --git a/src/library/scala/collection/LinearSeqLike.scala b/src/library/scala/collection/LinearSeqLike.scala index 78108a9c0f..ff7985bf0d 100644 --- a/src/library/scala/collection/LinearSeqLike.scala +++ b/src/library/scala/collection/LinearSeqLike.scala @@ -6,13 +6,10 @@ ** |/ ** \* */ +package scala +package collection -package scala.collection - -import generic._ -import mutable.ListBuffer import immutable.List -import scala.util.control.Breaks._ import scala.annotation.tailrec /** A template trait for linear sequences of type `LinearSeq[A]`. @@ -59,14 +56,14 @@ trait LinearSeqLike[+A, +Repr <: LinearSeqLike[A, Repr]] extends SeqLike[A, Repr def next(): A = if (hasNext) { val result = these.head; these = these.tail; result - } else Iterator.empty.next + } else Iterator.empty.next() /** Have to clear `these` so the iterator is exhausted like * it would be without the optimization. */ override def toList: List[A] = { val xs = these.toList - these = newBuilder.result + these = newBuilder.result() xs } } diff --git a/src/library/scala/collection/LinearSeqOptimized.scala b/src/library/scala/collection/LinearSeqOptimized.scala index 81cccea519..8635b090b9 100755 --- a/src/library/scala/collection/LinearSeqOptimized.scala +++ b/src/library/scala/collection/LinearSeqOptimized.scala @@ -6,12 +6,11 @@ ** |/ ** \* */ -package scala.collection +package scala +package collection -import generic._ import mutable.ListBuffer import immutable.List -import scala.util.control.Breaks._ import scala.annotation.tailrec /** A template trait for linear sequences of type `LinearSeq[A]` which optimizes @@ -84,7 +83,7 @@ trait LinearSeqOptimized[+A, +Repr <: LinearSeqOptimized[A, Repr]] extends Linea } override /*SeqLike*/ - def contains(elem: Any): Boolean = { + def contains[A1 >: A](elem: A1): Boolean = { var these = this while (!these.isEmpty) { if (these.head == elem) return true @@ -92,7 +91,7 @@ trait LinearSeqOptimized[+A, +Repr <: LinearSeqOptimized[A, Repr]] extends Linea } false } - + override /*IterableLike*/ def find(p: A => Boolean): Option[A] = { var these = this @@ -113,7 +112,7 @@ trait LinearSeqOptimized[+A, +Repr <: LinearSeqOptimized[A, Repr]] extends Linea } acc } - + override /*IterableLike*/ def foldRight[B](z: B)(f: (A, B) => B): B = if (this.isEmpty) z @@ -152,7 +151,7 @@ trait LinearSeqOptimized[+A, +Repr <: LinearSeqOptimized[A, Repr]] extends Linea b += these.head these = these.tail } - b.result + b.result() } override /*TraversableLike*/ @@ -187,7 +186,7 @@ trait LinearSeqOptimized[+A, +Repr <: LinearSeqOptimized[A, Repr]] extends Linea these = these.tail lead = lead.tail } - b.result + b.result() } override /*IterableLike*/ @@ -195,7 +194,7 @@ trait LinearSeqOptimized[+A, +Repr <: LinearSeqOptimized[A, Repr]] extends Linea var these: Repr = repr var count = from max 0 if (until <= count) - return newBuilder.result + return newBuilder.result() val b = newBuilder var sliceElems = until - count @@ -208,7 +207,7 @@ trait LinearSeqOptimized[+A, +Repr <: LinearSeqOptimized[A, Repr]] extends Linea b += these.head these = these.tail } - b.result + b.result() } override /*IterableLike*/ @@ -219,7 +218,7 @@ trait LinearSeqOptimized[+A, +Repr <: LinearSeqOptimized[A, Repr]] extends Linea b += these.head these = these.tail } - b.result + b.result() } override /*TraversableLike*/ @@ -230,7 +229,7 @@ trait LinearSeqOptimized[+A, +Repr <: LinearSeqOptimized[A, Repr]] extends Linea b += these.head these = these.tail } - (b.result, these) + (b.result(), these) } override /*IterableLike*/ diff --git a/src/library/scala/collection/Map.scala b/src/library/scala/collection/Map.scala index 18ad20a855..1e40fd8c24 100644 --- a/src/library/scala/collection/Map.scala +++ b/src/library/scala/collection/Map.scala @@ -6,7 +6,8 @@ ** |/ ** \* */ -package scala.collection +package scala +package collection import generic._ @@ -51,8 +52,8 @@ object Map extends MapFactory[Map] { def iterator = underlying.iterator override def default(key: A): B = d(key) } - + } /** Explicit instantiation of the `Map` trait to reduce class file size in subclasses. */ -private[scala] abstract class AbstractMap[A, +B] extends AbstractIterable[(A, B)] with Map[A, B] +abstract class AbstractMap[A, +B] extends AbstractIterable[(A, B)] with Map[A, B] diff --git a/src/library/scala/collection/MapLike.scala b/src/library/scala/collection/MapLike.scala index 93d02a435c..5ec7d5c615 100644 --- a/src/library/scala/collection/MapLike.scala +++ b/src/library/scala/collection/MapLike.scala @@ -6,8 +6,8 @@ ** |/ ** \* */ - -package scala.collection +package scala +package collection import generic._ import mutable.{ Builder, MapBuilder } @@ -181,7 +181,7 @@ self => def keysIterator: Iterator[A] = new AbstractIterator[A] { val iter = self.iterator def hasNext = iter.hasNext - def next() = iter.next._1 + def next() = iter.next()._1 } /** Collects all keys of this map in an iterable collection. @@ -213,7 +213,7 @@ self => def valuesIterator: Iterator[B] = new AbstractIterator[B] { val iter = self.iterator def hasNext = iter.hasNext - def next() = iter.next._2 + def next() = iter.next()._2 } /** Defines the default value computation for the map, diff --git a/src/library/scala/collection/MapProxy.scala b/src/library/scala/collection/MapProxy.scala index e85d306e6f..941c1f5a4a 100644 --- a/src/library/scala/collection/MapProxy.scala +++ b/src/library/scala/collection/MapProxy.scala @@ -6,7 +6,8 @@ ** |/ ** \* */ -package scala.collection +package scala +package collection /** This is a simple wrapper class for [[scala.collection.Map]]. * It is most useful for assembling customized map abstractions diff --git a/src/library/scala/collection/MapProxyLike.scala b/src/library/scala/collection/MapProxyLike.scala index 44b39f65da..dd80a538e3 100644 --- a/src/library/scala/collection/MapProxyLike.scala +++ b/src/library/scala/collection/MapProxyLike.scala @@ -6,9 +6,8 @@ ** |/ ** \* */ -package scala.collection - -import generic._ +package scala +package collection // Methods could be printed by cat MapLike.scala | egrep '^ (override )?def' @@ -19,6 +18,7 @@ import generic._ * @version 2.8 * @since 2.8 */ +@deprecated("Proxying is deprecated due to lack of use and compiler-level support.", "2.11.0") trait MapProxyLike[A, +B, +This <: MapLike[A, B, This] with Map[A, B]] extends MapLike[A, B, This] with IterableProxyLike[(A, B), This] diff --git a/src/library/scala/collection/Parallel.scala b/src/library/scala/collection/Parallel.scala index 6731f74bea..174e3ab75e 100644 --- a/src/library/scala/collection/Parallel.scala +++ b/src/library/scala/collection/Parallel.scala @@ -6,7 +6,8 @@ ** |/ ** \* */ -package scala.collection +package scala +package collection /** A marker trait for collections which have their operations parallelised. * diff --git a/src/library/scala/collection/Parallelizable.scala b/src/library/scala/collection/Parallelizable.scala index d97c44abc0..b737752458 100644 --- a/src/library/scala/collection/Parallelizable.scala +++ b/src/library/scala/collection/Parallelizable.scala @@ -6,7 +6,8 @@ ** |/ ** \* */ -package scala.collection +package scala +package collection import parallel.Combiner @@ -39,7 +40,7 @@ trait Parallelizable[+A, +ParRepr <: Parallel] extends Any { def par: ParRepr = { val cb = parCombiner for (x <- seq) cb += x - cb.result + cb.result() } /** The default `par` implementation uses the combiner provided by this method diff --git a/src/library/scala/collection/Searching.scala b/src/library/scala/collection/Searching.scala new file mode 100644 index 0000000000..fec4bbf502 --- /dev/null +++ b/src/library/scala/collection/Searching.scala @@ -0,0 +1,118 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +package scala +package collection + +import scala.language.implicitConversions +import scala.annotation.tailrec +import scala.collection.generic.IsSeqLike +import scala.math.Ordering + +/** A collection of wrappers that provide sequence classes with search functionality. + * + * Example usage: + * {{{ + * import scala.collection.Searching._ + * val l = List(1, 2, 3, 4, 5) + * l.search(3) + * // == Found(2) + * }}} + */ +object Searching { + sealed abstract class SearchResult { + def insertionPoint: Int + } + + case class Found(foundIndex: Int) extends SearchResult { + override def insertionPoint = foundIndex + } + case class InsertionPoint(insertionPoint: Int) extends SearchResult + + class SearchImpl[A, Repr](val coll: SeqLike[A, Repr]) { + /** Search the sorted sequence for a specific element. If the sequence is an + * `IndexedSeq`, a binary search is used. Otherwise, a linear search is used. + * + * The sequence should be sorted with the same `Ordering` before calling; otherwise, + * the results are undefined. + * + * @see [[scala.collection.IndexedSeq]] + * @see [[scala.math.Ordering]] + * @see [[scala.collection.SeqLike]], method `sorted` + * + * @param elem the element to find. + * @param ord the ordering to be used to compare elements. + * + * @return a `Found` value containing the index corresponding to the element in the + * sequence, or the `InsertionPoint` where the element would be inserted if + * the element is not in the sequence. + */ + final def search[B >: A](elem: B)(implicit ord: Ordering[B]): SearchResult = + coll match { + case _: IndexedSeq[A] => binarySearch(elem, -1, coll.length)(ord) + case _ => linearSearch(coll.view, elem, 0)(ord) + } + + /** Search within an interval in the sorted sequence for a specific element. If the + * sequence is an IndexedSeq, a binary search is used. Otherwise, a linear search + * is used. + * + * The sequence should be sorted with the same `Ordering` before calling; otherwise, + * the results are undefined. + * + * @see [[scala.collection.IndexedSeq]] + * @see [[scala.math.Ordering]] + * @see [[scala.collection.SeqLike]], method `sorted` + * + * @param elem the element to find. + * @param from the index where the search starts. + * @param to the index following where the search ends. + * @param ord the ordering to be used to compare elements. + * + * @return a `Found` value containing the index corresponding to the element in the + * sequence, or the `InsertionPoint` where the element would be inserted if + * the element is not in the sequence. + */ + final def search[B >: A](elem: B, from: Int, to: Int) + (implicit ord: Ordering[B]): SearchResult = + coll match { + case _: IndexedSeq[A] => binarySearch(elem, from-1, to)(ord) + case _ => linearSearch(coll.view(from, to), elem, from)(ord) + } + + @tailrec + private def binarySearch[B >: A](elem: B, from: Int, to: Int) + (implicit ord: Ordering[B]): SearchResult = { + if ((to-from) == 1) InsertionPoint(from) else { + val idx = from+(to-from)/2 + math.signum(ord.compare(elem, coll(idx))) match { + case -1 => binarySearch(elem, from, idx)(ord) + case 1 => binarySearch(elem, idx, to)(ord) + case _ => Found(idx) + } + } + } + + private def linearSearch[B >: A](c: SeqView[A, Repr], elem: B, offset: Int) + (implicit ord: Ordering[B]): SearchResult = { + var idx = offset + val it = c.iterator + while (it.hasNext) { + val cur = it.next() + if (ord.equiv(elem, cur)) return Found(idx) + else if (ord.lt(elem, cur)) return InsertionPoint(idx-1) + idx += 1 + } + InsertionPoint(idx) + } + + } + + implicit def search[Repr, A](coll: Repr) + (implicit fr: IsSeqLike[Repr]): SearchImpl[fr.A, Repr] = new SearchImpl(fr.conversion(coll)) +} diff --git a/src/library/scala/collection/Seq.scala b/src/library/scala/collection/Seq.scala index 33e66c0874..2f4b3e5f8a 100644 --- a/src/library/scala/collection/Seq.scala +++ b/src/library/scala/collection/Seq.scala @@ -6,7 +6,8 @@ ** |/ ** \* */ -package scala.collection +package scala +package collection import generic._ import mutable.Builder @@ -37,4 +38,4 @@ object Seq extends SeqFactory[Seq] { } /** Explicit instantiation of the `Seq` trait to reduce class file size in subclasses. */ -private[scala] abstract class AbstractSeq[+A] extends AbstractIterable[A] with Seq[A] +abstract class AbstractSeq[+A] extends AbstractIterable[A] with Seq[A] diff --git a/src/library/scala/collection/SeqExtractors.scala b/src/library/scala/collection/SeqExtractors.scala index 20ea7f54b7..2398313c77 100644 --- a/src/library/scala/collection/SeqExtractors.scala +++ b/src/library/scala/collection/SeqExtractors.scala @@ -1,4 +1,5 @@ -package scala.collection +package scala +package collection /** An extractor used to head/tail deconstruct sequences. */ object +: { diff --git a/src/library/scala/collection/SeqLike.scala b/src/library/scala/collection/SeqLike.scala index 1be0dba29f..fdfb1f2efc 100644 --- a/src/library/scala/collection/SeqLike.scala +++ b/src/library/scala/collection/SeqLike.scala @@ -107,7 +107,7 @@ trait SeqLike[+A, +Repr] extends Any with IterableLike[A, Repr] with GenSeqLike[ def segmentLength(p: A => Boolean, from: Int): Int = { var i = 0 - var it = iterator.drop(from) + val it = iterator.drop(from) while (it.hasNext && p(it.next())) i += 1 i @@ -115,7 +115,7 @@ trait SeqLike[+A, +Repr] extends Any with IterableLike[A, Repr] with GenSeqLike[ def indexWhere(p: A => Boolean, from: Int): Int = { var i = from - var it = iterator.drop(from) + val it = iterator.drop(from) while (it.hasNext) { if (p(it.next())) return i else i += 1 @@ -127,7 +127,7 @@ trait SeqLike[+A, +Repr] extends Any with IterableLike[A, Repr] with GenSeqLike[ def lastIndexWhere(p: A => Boolean, end: Int): Int = { var i = length - 1 val it = reverseIterator - while (it.hasNext && { val elem = it.next; (i > end || !p(elem)) }) i -= 1 + while (it.hasNext && { val elem = it.next(); (i > end || !p(elem)) }) i -= 1 i } @@ -156,10 +156,10 @@ trait SeqLike[+A, +Repr] extends Any with IterableLike[A, Repr] with GenSeqLike[ def hasNext = _hasNext def next(): Repr = { if (!hasNext) - Iterator.empty.next + Iterator.empty.next() val forcedElms = new mutable.ArrayBuffer[A](elms.size) ++= elms - val result = (self.newBuilder ++= forcedElms).result + val result = (self.newBuilder ++= forcedElms).result() var i = idxs.length - 2 while(i >= 0 && idxs(i) >= idxs(i+1)) i -= 1 @@ -181,10 +181,10 @@ trait SeqLike[+A, +Repr] extends Any with IterableLike[A, Repr] with GenSeqLike[ result } private def swap(i: Int, j: Int) { - var tmpI = idxs(i) + val tmpI = idxs(i) idxs(i) = idxs(j) idxs(j) = tmpI - var tmpE = elms(i) + val tmpE = elms(i) elms(i) = elms(j) elms(j) = tmpE } @@ -208,15 +208,15 @@ trait SeqLike[+A, +Repr] extends Any with IterableLike[A, Repr] with GenSeqLike[ def hasNext = _hasNext def next(): Repr = { if (!hasNext) - Iterator.empty.next + Iterator.empty.next() - /** Calculate this result. */ + /* Calculate this result. */ val buf = self.newBuilder for(k <- 0 until nums.length; j <- 0 until nums(k)) buf += elms(offs(k)+j) - val res = buf.result + val res = buf.result() - /** Prepare for the next call to next. */ + /* Prepare for the next call to next. */ var idx = nums.length - 1 while (idx >= 0 && nums(idx) == cnts(idx)) idx -= 1 @@ -268,18 +268,18 @@ trait SeqLike[+A, +Repr] extends Any with IterableLike[A, Repr] with GenSeqLike[ b.sizeHint(this) for (x <- xs) b += x - b.result + b.result() } def reverseMap[B, That](f: A => B)(implicit bf: CanBuildFrom[Repr, B, That]): That = { var xs: List[A] = List() - for (x <- this.seq) + for (x <- this) xs = x :: xs val b = bf(repr) for (x <- xs) b += f(x) - b.result + b.result() } /** An iterator yielding elements in reversed order. @@ -335,7 +335,7 @@ trait SeqLike[+A, +Repr] extends Any with IterableLike[A, Repr] with GenSeqLike[ if (from > l) -1 else if (tl < 1) clippedFrom else if (l < tl) -1 - else SeqLike.kmpSearch(thisCollection, clippedFrom, l, that.seq, 0, tl, true) + else SeqLike.kmpSearch(thisCollection, clippedFrom, l, that.seq, 0, tl, forward = true) } else { var i = from @@ -372,7 +372,7 @@ trait SeqLike[+A, +Repr] extends Any with IterableLike[A, Repr] with GenSeqLike[ if (end < 0) -1 else if (tl < 1) clippedL else if (l < tl) -1 - else SeqLike.kmpSearch(thisCollection, 0, clippedL+tl, that.seq, 0, tl, false) + else SeqLike.kmpSearch(thisCollection, 0, clippedL+tl, that.seq, 0, tl, forward = false) } /** Tests whether this $coll contains a given sequence as a slice. @@ -390,7 +390,7 @@ trait SeqLike[+A, +Repr] extends Any with IterableLike[A, Repr] with GenSeqLike[ * @return `true` if this $coll has an element that is equal (as * determined by `==`) to `elem`, `false` otherwise. */ - def contains(elem: Any): Boolean = exists (_ == elem) + def contains[A1 >: A](elem: A1): Boolean = exists (_ == elem) /** Produces a new sequence which contains all elements of this $coll and also all elements of * a given sequence. `xs union ys` is equivalent to `xs ++ ys`. @@ -442,7 +442,7 @@ trait SeqLike[+A, +Repr] extends Any with IterableLike[A, Repr] with GenSeqLike[ for (x <- this) if (occ(x) == 0) b += x else occ(x) -= 1 - b.result + b.result() } /** Computes the multiset intersection between this $coll and another sequence. @@ -473,12 +473,12 @@ trait SeqLike[+A, +Repr] extends Any with IterableLike[A, Repr] with GenSeqLike[ b += x occ(x) -= 1 } - b.result + b.result() } private def occCounts[B](sq: Seq[B]): mutable.Map[B, Int] = { val occ = new mutable.HashMap[B, Int] { override def default(k: B) = 0 } - for (y <- sq.seq) occ(y) += 1 + for (y <- sq) occ(y) += 1 occ } @@ -496,7 +496,7 @@ trait SeqLike[+A, +Repr] extends Any with IterableLike[A, Repr] with GenSeqLike[ seen += x } } - b.result + b.result() } def patch[B >: A, That](from: Int, patch: GenSeq[B], replaced: Int)(implicit bf: CanBuildFrom[Repr, B, That]): That = { @@ -505,30 +505,33 @@ trait SeqLike[+A, +Repr] extends Any with IterableLike[A, Repr] with GenSeqLike[ b ++= toCollection(prefix) b ++= patch.seq b ++= toCollection(rest).view drop replaced - b.result + b.result() } def updated[B >: A, That](index: Int, elem: B)(implicit bf: CanBuildFrom[Repr, B, That]): That = { + if (index < 0) throw new IndexOutOfBoundsException(index.toString) val b = bf(repr) val (prefix, rest) = this.splitAt(index) + val restColl = toCollection(rest) + if (restColl.isEmpty) throw new IndexOutOfBoundsException(index.toString) b ++= toCollection(prefix) b += elem - b ++= toCollection(rest).view.tail - b.result + b ++= restColl.view.tail + b.result() } def +:[B >: A, That](elem: B)(implicit bf: CanBuildFrom[Repr, B, That]): That = { val b = bf(repr) b += elem b ++= thisCollection - b.result + b.result() } def :+[B >: A, That](elem: B)(implicit bf: CanBuildFrom[Repr, B, That]): That = { val b = bf(repr) b ++= thisCollection b += elem - b.result + b.result() } def padTo[B >: A, That](len: Int, elem: B)(implicit bf: CanBuildFrom[Repr, B, That]): That = { @@ -540,14 +543,14 @@ trait SeqLike[+A, +Repr] extends Any with IterableLike[A, Repr] with GenSeqLike[ b += elem diff -= 1 } - b.result + b.result() } def corresponds[B](that: GenSeq[B])(p: (A,B) => Boolean): Boolean = { val i = this.iterator val j = that.iterator while (i.hasNext && j.hasNext) - if (!p(i.next, j.next)) + if (!p(i.next(), j.next())) return false !i.hasNext && !j.hasNext @@ -608,7 +611,7 @@ trait SeqLike[+A, +Repr] extends Any with IterableLike[A, Repr] with GenSeqLike[ val len = this.length val arr = new ArraySeq[A](len) var i = 0 - for (x <- this.seq) { + for (x <- this) { arr(i) = x i += 1 } @@ -616,13 +619,13 @@ trait SeqLike[+A, +Repr] extends Any with IterableLike[A, Repr] with GenSeqLike[ val b = newBuilder b.sizeHint(len) for (x <- arr) b += x - b.result + b.result() } /** Converts this $coll to a sequence. * $willNotTerminateInf * - * Overridden for efficiency. + * A new collection will not be built; in particular, lazy sequences will stay lazy. */ override def toSeq: Seq[A] = thisCollection @@ -682,7 +685,7 @@ object SeqLike { val wit = W.iterator.drop(n0) var i = if (forward) 0 else (n1-n0-1) while (i != done) { - Warr(i) = wit.next.asInstanceOf[AnyRef] + Warr(i) = wit.next().asInstanceOf[AnyRef] i += delta } @@ -778,15 +781,15 @@ object SeqLike { case _ => // We had better not index into S directly! val iter = S.iterator.drop(m0) - val Wopt = kmpOptimizeWord(W, n0, n1, true) + val Wopt = kmpOptimizeWord(W, n0, n1, forward = true) val T = kmpJumpTable(Wopt, n1-n0) - var cache = new Array[AnyRef](n1-n0) // Ring buffer--need a quick way to do a look-behind + val cache = new Array[AnyRef](n1-n0) // Ring buffer--need a quick way to do a look-behind var largest = 0 var i, m = 0 var answer = -1 while (m+m0+n1-n0 <= m1) { while (i+m >= largest) { - cache(largest%(n1-n0)) = iter.next.asInstanceOf[AnyRef] + cache(largest%(n1-n0)) = iter.next().asInstanceOf[AnyRef] largest += 1 } if (Wopt(i) == cache((i+m)%(n1-n0))) { @@ -851,7 +854,7 @@ object SeqLike { else if (s1 - s0 < t1 - t0) -1 // Source is too short to find target else { // Nontrivial search - val ans = kmpSearch(source, s0, s1, target, t0, t1, true) + val ans = kmpSearch(source, s0, s1, target, t0, t1, forward = true) if (ans < 0) ans else ans - math.min(slen, sourceOffset) } } @@ -883,7 +886,7 @@ object SeqLike { else if (fixed_s1 - s0 < t1 - t0) -1 // Source is too short to find target else { // Nontrivial search - val ans = kmpSearch(source, s0, fixed_s1, target, t0, t1, false) + val ans = kmpSearch(source, s0, fixed_s1, target, t0, t1, forward = false) if (ans < 0) ans else ans - s0 } } diff --git a/src/library/scala/collection/SeqProxy.scala b/src/library/scala/collection/SeqProxy.scala index 1f8dc4aad1..f728ba8585 100644 --- a/src/library/scala/collection/SeqProxy.scala +++ b/src/library/scala/collection/SeqProxy.scala @@ -8,7 +8,8 @@ -package scala.collection +package scala +package collection /** This trait implements a proxy for sequence objects. It forwards * all calls to a different sequence object. @@ -17,4 +18,5 @@ package scala.collection * @version 2.8 * @since 2.8 */ +@deprecated("Proxying is deprecated due to lack of use and compiler-level support.", "2.11.0") trait SeqProxy[+A] extends Seq[A] with SeqProxyLike[A, Seq[A]] diff --git a/src/library/scala/collection/SeqProxyLike.scala b/src/library/scala/collection/SeqProxyLike.scala index 5e8030d1e4..b01d227d10 100644 --- a/src/library/scala/collection/SeqProxyLike.scala +++ b/src/library/scala/collection/SeqProxyLike.scala @@ -8,7 +8,8 @@ -package scala.collection +package scala +package collection import generic._ @@ -22,6 +23,7 @@ import generic._ * @version 2.8 * @since 2.8 */ +@deprecated("Proxying is deprecated due to lack of use and compiler-level support.", "2.11.0") trait SeqProxyLike[+A, +Repr <: SeqLike[A, Repr] with Seq[A]] extends SeqLike[A, Repr] with IterableProxyLike[A, Repr] { override def size = self.size override def toSeq: Seq[A] = self.toSeq @@ -50,7 +52,7 @@ trait SeqProxyLike[+A, +Repr <: SeqLike[A, Repr] with Seq[A]] extends SeqLike[A, override def lastIndexOfSlice[B >: A](that: GenSeq[B]): Int = self.lastIndexOfSlice(that) override def lastIndexOfSlice[B >: A](that: GenSeq[B], end: Int): Int = self.lastIndexOfSlice(that, end) override def containsSlice[B](that: GenSeq[B]): Boolean = self.indexOfSlice(that) != -1 - override def contains(elem: Any): Boolean = self.contains(elem) + override def contains[A1 >: A](elem: A1): Boolean = self.contains(elem) override def union[B >: A, That](that: GenSeq[B])(implicit bf: CanBuildFrom[Repr, B, That]): That = self.union(that)(bf) override def diff[B >: A](that: GenSeq[B]): Repr = self.diff(that) override def intersect[B >: A](that: GenSeq[B]): Repr = self.intersect(that) diff --git a/src/library/scala/collection/SeqView.scala b/src/library/scala/collection/SeqView.scala index c26124cf6f..4afc5bffcd 100644 --- a/src/library/scala/collection/SeqView.scala +++ b/src/library/scala/collection/SeqView.scala @@ -8,7 +8,8 @@ -package scala.collection +package scala +package collection import generic._ import TraversableView.NoBuilder @@ -16,7 +17,7 @@ import TraversableView.NoBuilder /** A base trait for non-strict views of sequences. * $seqViewInfo */ -trait SeqView[+A, +Coll] extends SeqViewLike[A, Coll, SeqView[A, Coll]] with GenSeqView[A, Coll] +trait SeqView[+A, +Coll] extends SeqViewLike[A, Coll, SeqView[A, Coll]] /** An object containing the necessary implicit definitions to make * `SeqView`s work. Its definitions are generally not accessed directly by clients. diff --git a/src/library/scala/collection/SeqViewLike.scala b/src/library/scala/collection/SeqViewLike.scala index 5f2bf902b1..5e31ac4a53 100644 --- a/src/library/scala/collection/SeqViewLike.scala +++ b/src/library/scala/collection/SeqViewLike.scala @@ -6,11 +6,11 @@ ** |/ ** \* */ -package scala.collection +package scala +package collection import generic._ import Seq.fill -import TraversableView.NoBuilder /** A template trait for non-strict views of sequences. * $seqViewInfo @@ -30,45 +30,153 @@ import TraversableView.NoBuilder trait SeqViewLike[+A, +Coll, +This <: SeqView[A, Coll] with SeqViewLike[A, Coll, This]] - extends Seq[A] with SeqLike[A, This] with IterableView[A, Coll] with IterableViewLike[A, Coll, This] with GenSeqViewLike[A, Coll, This] + extends Seq[A] with SeqLike[A, This] with IterableView[A, Coll] with IterableViewLike[A, Coll, This] { self => - trait Transformed[+B] extends SeqView[B, Coll] with super[IterableViewLike].Transformed[B] with super[GenSeqViewLike].Transformed[B] { + /** Explicit instantiation of the `Transformed` trait to reduce class file size in subclasses. */ + private[collection] abstract class AbstractTransformed[+B] extends Seq[B] with super[IterableViewLike].Transformed[B] with Transformed[B] + + trait Transformed[+B] extends SeqView[B, Coll] with super.Transformed[B] { def length: Int def apply(idx: Int): B override def toString = viewToString } - /** Explicit instantiation of the `Transformed` trait to reduce class file size in subclasses. */ - private[collection] abstract class AbstractTransformed[+B] extends Seq[B] with super[IterableViewLike].Transformed[B] with Transformed[B] + trait EmptyView extends Transformed[Nothing] with super.EmptyView { + final override def length = 0 + final override def apply(n: Int) = Nil(n) + } - trait EmptyView extends Transformed[Nothing] with super[IterableViewLike].EmptyView with super[GenSeqViewLike].EmptyView + trait Forced[B] extends super.Forced[B] with Transformed[B] { + def length = forced.length + def apply(idx: Int) = forced.apply(idx) + } - trait Forced[B] extends super[IterableViewLike].Forced[B] with super[GenSeqViewLike].Forced[B] with Transformed[B] + trait Sliced extends super.Sliced with Transformed[A] { + def length = iterator.size + def apply(idx: Int): A = + if (idx + from < until) self.apply(idx + from) + else throw new IndexOutOfBoundsException(idx.toString) - trait Sliced extends super[IterableViewLike].Sliced with super[GenSeqViewLike].Sliced with Transformed[A] + override def foreach[U](f: A => U) = iterator foreach f + override def iterator: Iterator[A] = self.iterator drop from take endpoints.width + } - trait Mapped[B] extends super[IterableViewLike].Mapped[B] with super[GenSeqViewLike].Mapped[B] with Transformed[B] + trait Mapped[B] extends super.Mapped[B] with Transformed[B] { + def length = self.length + def apply(idx: Int): B = mapping(self(idx)) + } - trait FlatMapped[B] extends super[IterableViewLike].FlatMapped[B] with super[GenSeqViewLike].FlatMapped[B] with Transformed[B] + trait FlatMapped[B] extends super.FlatMapped[B] with Transformed[B] { + protected[this] lazy val index = { + val index = new Array[Int](self.length + 1) + index(0) = 0 + for (i <- 0 until self.length) // note that if the mapping returns a list, performance is bad, bad + index(i + 1) = index(i) + mapping(self(i)).seq.size + index + } + protected[this] def findRow(idx: Int, lo: Int, hi: Int): Int = { + val mid = (lo + hi) / 2 + if (idx < index(mid)) findRow(idx, lo, mid - 1) + else if (idx >= index(mid + 1)) findRow(idx, mid + 1, hi) + else mid + } + def length = index(self.length) + def apply(idx: Int) = { + val row = findRow(idx, 0, self.length - 1) + mapping(self(row)).seq.toSeq(idx - index(row)) + } + } - trait Appended[B >: A] extends super[IterableViewLike].Appended[B] with super[GenSeqViewLike].Appended[B] with Transformed[B] + trait Appended[B >: A] extends super.Appended[B] with Transformed[B] { + protected[this] lazy val restSeq = rest.toSeq + def length = self.length + restSeq.length + def apply(idx: Int) = + if (idx < self.length) self(idx) else restSeq(idx - self.length) + } - trait Filtered extends super[IterableViewLike].Filtered with super[GenSeqViewLike].Filtered with Transformed[A] + trait Filtered extends super.Filtered with Transformed[A] { + protected[this] lazy val index = { + var len = 0 + val arr = new Array[Int](self.length) + for (i <- 0 until self.length) + if (pred(self(i))) { + arr(len) = i + len += 1 + } + arr take len + } + def length = index.length + def apply(idx: Int) = self(index(idx)) + } - trait TakenWhile extends super[IterableViewLike].TakenWhile with super[GenSeqViewLike].TakenWhile with Transformed[A] + trait TakenWhile extends super.TakenWhile with Transformed[A] { + protected[this] lazy val len = self prefixLength pred + def length = len + def apply(idx: Int) = + if (idx < len) self(idx) + else throw new IndexOutOfBoundsException(idx.toString) + } - trait DroppedWhile extends super[IterableViewLike].DroppedWhile with super[GenSeqViewLike].DroppedWhile with Transformed[A] + trait DroppedWhile extends super.DroppedWhile with Transformed[A] { + protected[this] lazy val start = self prefixLength pred + def length = self.length - start + def apply(idx: Int) = + if (idx >= 0) self(idx + start) + else throw new IndexOutOfBoundsException(idx.toString) + } - trait Zipped[B] extends super[IterableViewLike].Zipped[B] with super[GenSeqViewLike].Zipped[B] with Transformed[(A, B)] + trait Zipped[B] extends super.Zipped[B] with Transformed[(A, B)] { + protected[this] lazy val thatSeq = other.seq.toSeq + /* Have to be careful here - other may be an infinite sequence. */ + def length = if ((thatSeq lengthCompare self.length) <= 0) thatSeq.length else self.length + def apply(idx: Int) = (self.apply(idx), thatSeq.apply(idx)) + } - trait ZippedAll[A1 >: A, B] extends super[IterableViewLike].ZippedAll[A1, B] with super[GenSeqViewLike].ZippedAll[A1, B] with Transformed[(A1, B)] + trait ZippedAll[A1 >: A, B] extends super.ZippedAll[A1, B] with Transformed[(A1, B)] { + protected[this] lazy val thatSeq = other.seq.toSeq + def length: Int = self.length max thatSeq.length + def apply(idx: Int) = + (if (idx < self.length) self.apply(idx) else thisElem, + if (idx < thatSeq.length) thatSeq.apply(idx) else thatElem) + } - trait Reversed extends Transformed[A] with super[GenSeqViewLike].Reversed + trait Reversed extends Transformed[A] { + override def iterator: Iterator[A] = createReversedIterator + def length: Int = self.length + def apply(idx: Int): A = self.apply(length - 1 - idx) + final override protected[this] def viewIdentifier = "R" + + private def createReversedIterator = { + var lst = List[A]() + for (elem <- self) lst ::= elem + lst.iterator + } + } - trait Patched[B >: A] extends Transformed[B] with super[GenSeqViewLike].Patched[B] + trait Patched[B >: A] extends Transformed[B] { + protected[this] val from: Int + protected[this] val patch: GenSeq[B] + protected[this] val replaced: Int + private lazy val plen = patch.length + override def iterator: Iterator[B] = self.iterator patch (from, patch.iterator, replaced) + def length: Int = self.length + plen - replaced + def apply(idx: Int): B = + if (idx < from) self.apply(idx) + else if (idx < from + plen) patch.apply(idx - from) + else self.apply(idx - plen + replaced) + final override protected[this] def viewIdentifier = "P" + } - trait Prepended[B >: A] extends Transformed[B] with super[GenSeqViewLike].Prepended[B] + trait Prepended[B >: A] extends Transformed[B] { + protected[this] val fst: B + override def iterator: Iterator[B] = Iterator.single(fst) ++ self.iterator + def length: Int = 1 + self.length + def apply(idx: Int): B = + if (idx == 0) fst + else self.apply(idx - 1) + final override protected[this] def viewIdentifier = "A" + } /** Boilerplate method, to override in each subclass * This method could be eliminated if Scala had virtual classes @@ -137,5 +245,20 @@ trait SeqViewLike[+A, override def sorted[B >: A](implicit ord: Ordering[B]): This = newForced(thisSeq sorted ord).asInstanceOf[This] + override def sortWith(lt: (A, A) => Boolean): This = + newForced(thisSeq sortWith lt).asInstanceOf[This] + + override def sortBy[B](f: (A) => B)(implicit ord: Ordering[B]): This = + newForced(thisSeq sortBy f).asInstanceOf[This] + + override def combinations(n: Int): Iterator[This] = + (thisSeq combinations n).map(as => newForced(as).asInstanceOf[This]) + + override def permutations: Iterator[This] = + thisSeq.permutations.map(as => newForced(as).asInstanceOf[This]) + + override def distinct: This = + newForced(thisSeq.distinct).asInstanceOf[This] + override def stringPrefix = "SeqView" } diff --git a/src/library/scala/collection/Sequentializable.scala.disabled b/src/library/scala/collection/Sequentializable.scala.disabled deleted file mode 100644 index df457671a6..0000000000 --- a/src/library/scala/collection/Sequentializable.scala.disabled +++ /dev/null @@ -1,10 +0,0 @@ -package scala.collection - - - - -trait Sequentializable[+T, +Repr] { - - def seq: Repr - -} diff --git a/src/library/scala/collection/Set.scala b/src/library/scala/collection/Set.scala index c304323d28..f74c26571a 100644 --- a/src/library/scala/collection/Set.scala +++ b/src/library/scala/collection/Set.scala @@ -6,8 +6,8 @@ ** |/ ** \* */ - -package scala.collection +package scala +package collection import generic._ @@ -44,4 +44,4 @@ object Set extends SetFactory[Set] { } /** Explicit instantiation of the `Set` trait to reduce class file size in subclasses. */ -private[scala] abstract class AbstractSet[A] extends AbstractIterable[A] with Set[A] +abstract class AbstractSet[A] extends AbstractIterable[A] with Set[A] diff --git a/src/library/scala/collection/SetLike.scala b/src/library/scala/collection/SetLike.scala index a6ebcc0e20..0c5c7e0b29 100644 --- a/src/library/scala/collection/SetLike.scala +++ b/src/library/scala/collection/SetLike.scala @@ -6,8 +6,8 @@ ** |/ ** \* */ - -package scala.collection +package scala +package collection import generic._ import mutable.{ Builder, SetBuilder } @@ -180,14 +180,14 @@ self => def hasNext = len <= elms.size || itr.hasNext def next = { if (!itr.hasNext) { - if (len > elms.size) Iterator.empty.next + if (len > elms.size) Iterator.empty.next() else { itr = new SubsetsItr(elms, len) len += 1 } } - itr.next + itr.next() } } @@ -205,11 +205,11 @@ self => def hasNext = _hasNext def next(): This = { - if (!hasNext) Iterator.empty.next + if (!hasNext) Iterator.empty.next() val buf = self.newBuilder idxs.slice(0, len) foreach (idx => buf += elms(idx)) - val result = buf.result + val result = buf.result() var i = len - 1 while (i >= 0 && idxs(i) == idxs(i+1)-1) i -= 1 diff --git a/src/library/scala/collection/SetProxy.scala b/src/library/scala/collection/SetProxy.scala index 08075a7121..f9f38f148a 100644 --- a/src/library/scala/collection/SetProxy.scala +++ b/src/library/scala/collection/SetProxy.scala @@ -6,7 +6,8 @@ ** |/ ** \* */ -package scala.collection +package scala +package collection /** This is a simple wrapper class for [[scala.collection.Set]]. * It is most useful for assembling customized set abstractions diff --git a/src/library/scala/collection/SetProxyLike.scala b/src/library/scala/collection/SetProxyLike.scala index 5196f39917..4cd215cd89 100644 --- a/src/library/scala/collection/SetProxyLike.scala +++ b/src/library/scala/collection/SetProxyLike.scala @@ -6,10 +6,8 @@ ** |/ ** \* */ - -package scala.collection - -import generic._ +package scala +package collection // Methods could be printed by cat SetLike.scala | egrep '^ (override )?def' @@ -19,6 +17,7 @@ import generic._ * @author Martin Odersky * @version 2.8 */ +@deprecated("Proxying is deprecated due to lack of use and compiler-level support.", "2.11.0") trait SetProxyLike[A, +This <: SetLike[A, This] with Set[A]] extends SetLike[A, This] with IterableProxyLike[A, This] { def empty: This override def contains(elem: A): Boolean = self.contains(elem) diff --git a/src/library/scala/collection/SortedMap.scala b/src/library/scala/collection/SortedMap.scala index c81c16e8bb..36e7eae79c 100644 --- a/src/library/scala/collection/SortedMap.scala +++ b/src/library/scala/collection/SortedMap.scala @@ -6,7 +6,8 @@ ** |/ ** \* */ -package scala.collection +package scala +package collection import generic._ import mutable.Builder @@ -33,24 +34,20 @@ object SortedMap extends SortedMapFactory[SortedMap] { def empty[A, B](implicit ord: Ordering[A]): SortedMap[A, B] = immutable.SortedMap.empty[A, B](ord) implicit def canBuildFrom[A, B](implicit ord: Ordering[A]): CanBuildFrom[Coll, (A, B), SortedMap[A, B]] = new SortedMapCanBuildFrom[A, B] - + private[collection] trait Default[A, +B] extends SortedMap[A, B] { self => override def +[B1 >: B](kv: (A, B1)): SortedMap[A, B1] = { val b = SortedMap.newBuilder[A, B1] b ++= this b += ((kv._1, kv._2)) - b.result + b.result() } - + override def - (key: A): SortedMap[A, B] = { val b = newBuilder for (kv <- this; if kv._1 != key) b += kv - b.result + b.result() } } - } - - - diff --git a/src/library/scala/collection/SortedMapLike.scala b/src/library/scala/collection/SortedMapLike.scala index 57ad3497c7..cf5e9c36c7 100644 --- a/src/library/scala/collection/SortedMapLike.scala +++ b/src/library/scala/collection/SortedMapLike.scala @@ -6,9 +6,8 @@ ** |/ ** \* */ - - -package scala.collection +package scala +package collection import generic._ @@ -42,6 +41,7 @@ self => val map = self.rangeImpl(from, until) new map.DefaultKeySortedSet } + override def keysIteratorFrom(start: A) = self.keysIteratorFrom(start) } /** Add a key/value pair to this map. @@ -68,21 +68,27 @@ self => * @param elems the remaining elements to add. */ override def + [B1 >: B] (elem1: (A, B1), elem2: (A, B1), elems: (A, B1) *): SortedMap[A, B1] = { - var m = this + elem1 + elem2; + var m = this + elem1 + elem2 for (e <- elems) m = m + e m } - + override def filterKeys(p: A => Boolean): SortedMap[A, B] = new FilteredKeys(p) with SortedMap.Default[A, B] { implicit def ordering: Ordering[A] = self.ordering override def rangeImpl(from : Option[A], until : Option[A]): SortedMap[A, B] = self.rangeImpl(from, until).filterKeys(p) + override def iteratorFrom(start: A) = self iteratorFrom start filter {case (k, _) => p(k)} + override def keysIteratorFrom(start: A) = self keysIteratorFrom start filter p + override def valuesIteratorFrom(start: A) = self iteratorFrom start collect {case (k,v) if p(k) => v} } - + override def mapValues[C](f: B => C): SortedMap[A, C] = new MappedValues(f) with SortedMap.Default[A, C] { implicit def ordering: Ordering[A] = self.ordering override def rangeImpl(from : Option[A], until : Option[A]): SortedMap[A, C] = self.rangeImpl(from, until).mapValues(f) + override def iteratorFrom(start: A) = (self iteratorFrom start) map {case (k,v) => (k, f(v))} + override def keysIteratorFrom(start: A) = self keysIteratorFrom start + override def valuesIteratorFrom(start: A) = self valuesIteratorFrom start map f } - + /** Adds a number of elements provided by a traversable object * and returns a new collection with the added elements. * @@ -90,9 +96,27 @@ self => */ override def ++[B1 >: B](xs: GenTraversableOnce[(A, B1)]): SortedMap[A, B1] = ((repr: SortedMap[A, B1]) /: xs.seq) (_ + _) - -} - - - + /** + * Creates an iterator over all the key/value pairs + * contained in this map having a key greater than or + * equal to `start` according to the ordering of + * this map. x.iteratorFrom(y) is equivalent + * to but often more efficient than x.from(y).iterator. + * + * @param start The lower bound (inclusive) + * on the keys to be returned + */ + def iteratorFrom(start: A): Iterator[(A, B)] + /** + * Creates an iterator over all the values contained in this + * map that are associated with a key greater than or equal to `start` + * according to the ordering of this map. x.valuesIteratorFrom(y) is + * equivalent to but often more efficient than + * x.from(y).valuesIterator. + * + * @param start The lower bound (inclusive) + * on the keys to be returned + */ + def valuesIteratorFrom(start: A): Iterator[B] +} diff --git a/src/library/scala/collection/SortedSet.scala b/src/library/scala/collection/SortedSet.scala index 2d5d4fb55e..43189d2e8c 100644 --- a/src/library/scala/collection/SortedSet.scala +++ b/src/library/scala/collection/SortedSet.scala @@ -7,7 +7,8 @@ \* */ -package scala.collection +package scala +package collection import generic._ /** A sorted set. diff --git a/src/library/scala/collection/SortedSetLike.scala b/src/library/scala/collection/SortedSetLike.scala index 71b45c72ff..c38ea1f3ce 100644 --- a/src/library/scala/collection/SortedSetLike.scala +++ b/src/library/scala/collection/SortedSetLike.scala @@ -7,7 +7,8 @@ \* */ -package scala.collection +package scala +package collection import generic._ /** A template for sets which are sorted. @@ -40,4 +41,14 @@ self => case that: SortedSet[_] if that.ordering == ordering => that.hasAll(this.iterator) case that => super.subsetOf(that) } + + /** + * Creates an iterator that contains all values from this collection + * greater than or equal to `start` according to the ordering of + * this collection. x.iteratorFrom(y) is equivalent to but will usually + * be more efficient than x.from(y).iterator + * + * @param start The lower-bound (inclusive) of the iterator + */ + def iteratorFrom(start: A): Iterator[A] = keysIteratorFrom(start) } diff --git a/src/library/scala/collection/Traversable.scala b/src/library/scala/collection/Traversable.scala index 36ef230a42..b53724c568 100644 --- a/src/library/scala/collection/Traversable.scala +++ b/src/library/scala/collection/Traversable.scala @@ -6,12 +6,11 @@ ** |/ ** \* */ - - -package scala.collection +package scala +package collection import generic._ -import mutable.{Builder, Buffer, ArrayBuffer, ListBuffer} +import mutable.Builder import scala.util.control.Breaks /** A trait for traversable collections. @@ -102,4 +101,4 @@ object Traversable extends TraversableFactory[Traversable] { self => } /** Explicit instantiation of the `Traversable` trait to reduce class file size in subclasses. */ -private[scala] abstract class AbstractTraversable[+A] extends Traversable[A] +abstract class AbstractTraversable[+A] extends Traversable[A] diff --git a/src/library/scala/collection/TraversableLike.scala b/src/library/scala/collection/TraversableLike.scala index 8b430ca3d2..d3a7db6968 100644 --- a/src/library/scala/collection/TraversableLike.scala +++ b/src/library/scala/collection/TraversableLike.scala @@ -6,7 +6,8 @@ ** |/ ** \* */ -package scala.collection +package scala +package collection import generic._ import mutable.{ Builder } @@ -86,7 +87,7 @@ trait TraversableLike[+A, +Repr] extends Any def repr: Repr = this.asInstanceOf[Repr] final def isTraversableAgain: Boolean = true - + /** The underlying collection seen as an instance of `$Coll`. * By default this is implemented as the current collection object itself, * but this can be overridden. @@ -174,7 +175,7 @@ trait TraversableLike[+A, +Repr] extends Any * * @usecase def ++:[B](that: TraversableOnce[B]): $Coll[B] * @inheritdoc - * + * * Example: * {{{ * scala> val x = List(1) @@ -252,18 +253,21 @@ trait TraversableLike[+A, +Repr] extends Any b.result } + private def filterImpl(p: A => Boolean, isFlipped: Boolean): Repr = { + val b = newBuilder + for (x <- this) + if (p(x) != isFlipped) b += x + + b.result + } + /** Selects all elements of this $coll which satisfy a predicate. * * @param p the predicate used to test elements. * @return a new $coll consisting of all elements of this $coll that satisfy the given * predicate `p`. The order of the elements is preserved. */ - def filter(p: A => Boolean): Repr = { - val b = newBuilder - for (x <- this) - if (p(x)) b += x - b.result - } + def filter(p: A => Boolean): Repr = filterImpl(p, isFlipped = false) /** Selects all elements of this $coll which do not satisfy a predicate. * @@ -271,11 +275,11 @@ trait TraversableLike[+A, +Repr] extends Any * @return a new $coll consisting of all elements of this $coll that do not satisfy the given * predicate `p`. The order of the elements is preserved. */ - def filterNot(p: A => Boolean): Repr = filter(!p(_)) + def filterNot(p: A => Boolean): Repr = filterImpl(p, isFlipped = true) def collect[B, That](pf: PartialFunction[A, B])(implicit bf: CanBuildFrom[Repr, B, That]): That = { val b = bf(repr) - for (x <- this) if (pf.isDefinedAt(x)) b += pf(x) + foreach(pf.runWith(b += _)) b.result } @@ -341,8 +345,8 @@ trait TraversableLike[+A, +Repr] extends Any * $mayNotTerminateInf * * @param p the predicate used to test elements. - * @return `true` if the given predicate `p` holds for all elements - * of this $coll, otherwise `false`. + * @return `true` if this $coll is empty, otherwise `true` if the given predicate `p` + * holds for all elements of this $coll, otherwise `false`. */ def forall(p: A => Boolean): Boolean = { var result = true @@ -358,8 +362,8 @@ trait TraversableLike[+A, +Repr] extends Any * $mayNotTerminateInf * * @param p the predicate used to test elements. - * @return `true` if the given predicate `p` holds for some of the - * elements of this $coll, otherwise `false`. + * @return `false` if this $coll is empty, otherwise `true` if the given predicate `p` + * holds for some of the elements of this $coll, otherwise `false` */ def exists(p: A => Boolean): Boolean = { var result = false @@ -477,7 +481,7 @@ trait TraversableLike[+A, +Repr] extends Any var follow = false val b = newBuilder b.sizeHint(this, -1) - for (x <- this.seq) { + for (x <- this) { if (follow) b += lst else follow = true lst = x @@ -502,7 +506,7 @@ trait TraversableLike[+A, +Repr] extends Any private[this] def sliceInternal(from: Int, until: Int, b: Builder[A, Repr]): Repr = { var i = 0 breakable { - for (x <- this.seq) { + for (x <- this) { if (i >= from) b += x i += 1 if (i >= until) break @@ -619,7 +623,9 @@ trait TraversableLike[+A, +Repr] extends Any } } + @deprecatedOverriding("Enforce contract of toTraversable that if it is Traversable it returns itself.", "2.11.0") def toTraversable: Traversable[A] = thisCollection + def toIterator: Iterator[A] = toStream.iterator def toStream: Stream[A] = toBuffer.toStream // Override to provide size hint. diff --git a/src/library/scala/collection/TraversableOnce.scala b/src/library/scala/collection/TraversableOnce.scala index a448ac2c09..a8c4e047ab 100644 --- a/src/library/scala/collection/TraversableOnce.scala +++ b/src/library/scala/collection/TraversableOnce.scala @@ -6,7 +6,8 @@ ** |/ ** \* */ -package scala.collection +package scala +package collection import mutable.{ Buffer, Builder, ListBuffer, ArrayBuffer } import generic.CanBuildFrom @@ -84,10 +85,9 @@ trait TraversableOnce[+A] extends Any with GenTraversableOnce[A] { */ def seq: TraversableOnce[A] - /** Presently these are abstract because the Traversable versions use - * breakable/break, and I wasn't sure enough of how that's supposed to - * function to consolidate them with the Iterator versions. - */ + // Presently these are abstract because the Traversable versions use + // breakable/break, and I wasn't sure enough of how that's supposed to + // function to consolidate them with the Iterator versions. def forall(p: A => Boolean): Boolean def exists(p: A => Boolean): Boolean def find(p: A => Boolean): Option[A] @@ -96,7 +96,7 @@ trait TraversableOnce[+A] extends Any with GenTraversableOnce[A] { // for internal use protected[this] def reversed = { var elems: List[A] = Nil - self.seq foreach (elems ::= _) + self foreach (elems ::= _) elems } @@ -128,10 +128,8 @@ trait TraversableOnce[+A] extends Any with GenTraversableOnce[A] { * @example `Seq("a", 1, 5L).collectFirst({ case x: Int => x*10 }) = Some(10)` */ def collectFirst[B](pf: PartialFunction[A, B]): Option[B] = { - for (x <- self.toIterator) { // make sure to use an iterator or `seq` - if (pf isDefinedAt x) - return Some(pf(x)) - } + // make sure to use an iterator or `seq` + self.toIterator.foreach(pf.runWith(b => return Some(b))) None } @@ -141,7 +139,7 @@ trait TraversableOnce[+A] extends Any with GenTraversableOnce[A] { def foldLeft[B](z: B)(op: (B, A) => B): B = { var result = z - this.seq foreach (x => result = op(result, x)) + this foreach (x => result = op(result, x)) result } @@ -198,7 +196,7 @@ trait TraversableOnce[+A] extends Any with GenTraversableOnce[A] { def fold[A1 >: A](z: A1)(op: (A1, A1) => A1): A1 = foldLeft(z)(op) - def aggregate[B](z: B)(seqop: (B, A) => B, combop: (B, B) => B): B = foldLeft(z)(seqop) + def aggregate[B](z: =>B)(seqop: (B, A) => B, combop: (B, B) => B): B = foldLeft(z)(seqop) def sum[B >: A](implicit num: Numeric[B]): B = foldLeft(num.zero)(num.plus) @@ -222,13 +220,37 @@ trait TraversableOnce[+A] extends Any with GenTraversableOnce[A] { if (isEmpty) throw new UnsupportedOperationException("empty.maxBy") - reduceLeft((x, y) => if (cmp.gteq(f(x), f(y))) x else y) + var maxF: B = null.asInstanceOf[B] + var maxElem: A = null.asInstanceOf[A] + var first = true + + for (elem <- self) { + val fx = f(elem) + if (first || cmp.gt(fx, maxF)) { + maxElem = elem + maxF = fx + first = false + } + } + maxElem } def minBy[B](f: A => B)(implicit cmp: Ordering[B]): A = { if (isEmpty) throw new UnsupportedOperationException("empty.minBy") - reduceLeft((x, y) => if (cmp.lteq(f(x), f(y))) x else y) + var minF: B = null.asInstanceOf[B] + var minElem: A = null.asInstanceOf[A] + var first = true + + for (elem <- self) { + val fx = f(elem) + if (first || cmp.lt(fx, minF)) { + minElem = elem + minF = fx + first = false + } + } + minElem } /** Copies all elements of this $coll to a buffer. @@ -271,7 +293,7 @@ trait TraversableOnce[+A] extends Any with GenTraversableOnce[A] { def to[Col[_]](implicit cbf: CanBuildFrom[Nothing, A, Col[A @uV]]): Col[A @uV] = { val b = cbf() b ++= seq - b.result + b.result() } def toMap[T, U](implicit ev: A <:< (T, U)): immutable.Map[T, U] = { @@ -279,7 +301,7 @@ trait TraversableOnce[+A] extends Any with GenTraversableOnce[A] { for (x <- self) b += x - b.result + b.result() } def mkString(start: String, sep: String, end: String): String = @@ -297,14 +319,14 @@ trait TraversableOnce[+A] extends Any with GenTraversableOnce[A] { * Example: * * {{{ - * scala> val a = LinkedList(1,2,3,4) - * a: scala.collection.mutable.LinkedList[Int] = LinkedList(1, 2, 3, 4) - * + * scala> val a = List(1,2,3,4) + * a: List[Int] = List(1, 2, 3, 4) + * * scala> val b = new StringBuilder() - * b: StringBuilder = - * - * scala> a.addString(b, "LinkedList(", ", ", ")") - * res1: StringBuilder = LinkedList(1, 2, 3, 4) + * b: StringBuilder = + * + * scala> a.addString(b , "List(" , ", " , ")") + * res5: StringBuilder = List(1, 2, 3, 4) * }}} * * @param b the string builder to which elements are appended. @@ -339,9 +361,9 @@ trait TraversableOnce[+A] extends Any with GenTraversableOnce[A] { * Example: * * {{{ - * scala> val a = LinkedList(1,2,3,4) - * a: scala.collection.mutable.LinkedList[Int] = LinkedList(1, 2, 3, 4) - * + * scala> val a = List(1,2,3,4) + * a: List[Int] = List(1, 2, 3, 4) + * * scala> val b = new StringBuilder() * b: StringBuilder = * @@ -362,14 +384,14 @@ trait TraversableOnce[+A] extends Any with GenTraversableOnce[A] { * Example: * * {{{ - * scala> val a = LinkedList(1,2,3,4) - * a: scala.collection.mutable.LinkedList[Int] = LinkedList(1, 2, 3, 4) - * + * scala> val a = List(1,2,3,4) + * a: List[Int] = List(1, 2, 3, 4) + * * scala> val b = new StringBuilder() * b: StringBuilder = * * scala> val h = a.addString(b) - * b: StringBuilder = 1234 + * h: StringBuilder = 1234 * }}} * @param b the string builder to which elements are appended. @@ -380,27 +402,22 @@ trait TraversableOnce[+A] extends Any with GenTraversableOnce[A] { object TraversableOnce { - @deprecated("use OnceCanBuildFrom instead", "2.10.0") - def traversableOnceCanBuildFrom[T] = new OnceCanBuildFrom[T] - @deprecated("use MonadOps instead", "2.10.0") - def wrapTraversableOnce[A](trav: TraversableOnce[A]) = new MonadOps(trav) - implicit def alternateImplicit[A](trav: TraversableOnce[A]) = new ForceImplicitAmbiguity implicit def flattenTraversableOnce[A, CC[_]](travs: TraversableOnce[CC[A]])(implicit ev: CC[A] => TraversableOnce[A]) = new FlattenOps[A](travs map ev) /* Functionality reused in Iterator.CanBuildFrom */ - private[collection] abstract class BufferedCanBuildFrom[A, Coll[X] <: TraversableOnce[X]] extends generic.CanBuildFrom[Coll[_], A, Coll[A]] { - def bufferToColl[B](buff: ArrayBuffer[B]): Coll[B] - def traversableToColl[B](t: GenTraversable[B]): Coll[B] + private[collection] abstract class BufferedCanBuildFrom[A, CC[X] <: TraversableOnce[X]] extends generic.CanBuildFrom[CC[_], A, CC[A]] { + def bufferToColl[B](buff: ArrayBuffer[B]): CC[B] + def traversableToColl[B](t: GenTraversable[B]): CC[B] - def newIterator: Builder[A, Coll[A]] = new ArrayBuffer[A] mapResult bufferToColl + def newIterator: Builder[A, CC[A]] = new ArrayBuffer[A] mapResult bufferToColl /** Creates a new builder on request of a collection. * @param from the collection requesting the builder to be created. * @return the result of invoking the `genericBuilder` method on `from`. */ - def apply(from: Coll[_]): Builder[A, Coll[A]] = from match { + def apply(from: CC[_]): Builder[A, CC[A]] = from match { case xs: generic.GenericTraversableTemplate[_, _] => xs.genericBuilder.asInstanceOf[Builder[A, Traversable[A]]] mapResult { case res => traversableToColl(res.asInstanceOf[GenTraversable[A]]) } @@ -429,7 +446,7 @@ object TraversableOnce { def flatten: Iterator[A] = new AbstractIterator[A] { val its = travs.toIterator private var it: Iterator[A] = Iterator.empty - def hasNext: Boolean = it.hasNext || its.hasNext && { it = its.next.toIterator; hasNext } + def hasNext: Boolean = it.hasNext || its.hasNext && { it = its.next().toIterator; hasNext } def next(): A = if (hasNext) it.next() else Iterator.empty.next() } } diff --git a/src/library/scala/collection/TraversableProxy.scala b/src/library/scala/collection/TraversableProxy.scala index 568298a9d9..65936da0e4 100644 --- a/src/library/scala/collection/TraversableProxy.scala +++ b/src/library/scala/collection/TraversableProxy.scala @@ -8,7 +8,8 @@ -package scala.collection +package scala +package collection // Methods could be printed by cat TraversableLike.scala | egrep '^ (override )?def' diff --git a/src/library/scala/collection/TraversableProxyLike.scala b/src/library/scala/collection/TraversableProxyLike.scala index 8896cd1b0f..4399dbc289 100644 --- a/src/library/scala/collection/TraversableProxyLike.scala +++ b/src/library/scala/collection/TraversableProxyLike.scala @@ -8,7 +8,8 @@ -package scala.collection +package scala +package collection import generic._ import mutable.{Buffer, StringBuilder} @@ -23,6 +24,7 @@ import scala.reflect.ClassTag * @version 2.8 * @since 2.8 */ +@deprecated("Proxying is deprecated due to lack of use and compiler-level support.", "2.11.0") trait TraversableProxyLike[+A, +Repr <: TraversableLike[A, Repr] with Traversable[A]] extends TraversableLike[A, Repr] with Proxy { def self: Repr diff --git a/src/library/scala/collection/TraversableView.scala b/src/library/scala/collection/TraversableView.scala index cce6b72257..cffce6ff8e 100644 --- a/src/library/scala/collection/TraversableView.scala +++ b/src/library/scala/collection/TraversableView.scala @@ -6,16 +6,16 @@ ** |/ ** \* */ -package scala.collection +package scala +package collection import generic._ import mutable.Builder -import TraversableView.NoBuilder /** A base trait for non-strict views of traversable collections. * $traversableViewInfo */ -trait TraversableView[+A, +Coll] extends TraversableViewLike[A, Coll, TraversableView[A, Coll]] with GenTraversableView[A, Coll] { } +trait TraversableView[+A, +Coll] extends TraversableViewLike[A, Coll, TraversableView[A, Coll]] { } /** An object containing the necessary implicit definitions to make * `TraversableView`s work. Its definitions are generally not accessed directly by clients. diff --git a/src/library/scala/collection/TraversableViewLike.scala b/src/library/scala/collection/TraversableViewLike.scala index 14f865c2f0..5926c69ebf 100644 --- a/src/library/scala/collection/TraversableViewLike.scala +++ b/src/library/scala/collection/TraversableViewLike.scala @@ -6,11 +6,11 @@ ** |/ ** \* */ -package scala.collection +package scala +package collection import generic._ import mutable.{ Builder, ArrayBuffer } -import TraversableView.NoBuilder import scala.annotation.migration import scala.language.implicitConversions @@ -59,7 +59,7 @@ trait ViewMkString[+A] { * $viewInfo * * All views for traversable collections are defined by creating a new `foreach` method. - * + * * @author Martin Odersky * @version 2.8 * @since 2.8 @@ -70,27 +70,39 @@ trait ViewMkString[+A] { trait TraversableViewLike[+A, +Coll, +This <: TraversableView[A, Coll] with TraversableViewLike[A, Coll, This]] - extends Traversable[A] with TraversableLike[A, This] with ViewMkString[A] with GenTraversableViewLike[A, Coll, This] + extends Traversable[A] with TraversableLike[A, This] with ViewMkString[A] { self => - override protected[this] def newBuilder: Builder[A, This] = - throw new UnsupportedOperationException(this+".newBuilder") - protected def underlying: Coll protected[this] def viewIdentifier: String = "" protected[this] def viewIdString: String = "" + def viewToString = stringPrefix + viewIdString + "(...)" override def stringPrefix = "TraversableView" + override protected[this] def newBuilder: Builder[A, This] = + throw new UnsupportedOperationException(this+".newBuilder") + def force[B >: A, That](implicit bf: CanBuildFrom[Coll, B, That]) = { val b = bf(underlying) b ++= this b.result() } - trait Transformed[+B] extends TraversableView[B, Coll] with super.Transformed[B] { + /** Explicit instantiation of the `Transformed` trait to reduce class file size in subclasses. */ + private[collection] abstract class AbstractTransformed[+B] extends Traversable[B] with Transformed[B] + + + /** The implementation base trait of this view. + * This trait and all its subtraits has to be re-implemented for each + * ViewLike class. + */ + trait Transformed[+B] extends TraversableView[B, Coll] { def foreach[U](f: B => U): Unit + lazy val underlying = self.underlying + final override protected[this] def viewIdString = self.viewIdString + viewIdentifier + // Methods whose standard implementations use "isEmpty" need to be rewritten // for views, else they will end up traversing twice in a situation like: // xs.view.flatMap(f).headOption @@ -116,29 +128,99 @@ trait TraversableViewLike[+A, override def toString = viewToString } - /** Explicit instantiation of the `Transformed` trait to reduce class file size in subclasses. */ - private[collection] abstract class AbstractTransformed[+B] extends Traversable[B] with Transformed[B] - - trait EmptyView extends Transformed[Nothing] with super.EmptyView + trait EmptyView extends Transformed[Nothing] { + final override def isEmpty = true + final override def foreach[U](f: Nothing => U): Unit = () + } /** A fall back which forces everything into a vector and then applies an operation * on it. Used for those operations which do not naturally lend themselves to a view */ - trait Forced[B] extends Transformed[B] with super.Forced[B] + trait Forced[B] extends Transformed[B] { + protected[this] val forced: GenSeq[B] + def foreach[U](f: B => U) = forced foreach f + final override protected[this] def viewIdentifier = "C" + } - trait Sliced extends Transformed[A] with super.Sliced + trait Sliced extends Transformed[A] { + protected[this] val endpoints: SliceInterval + protected[this] def from = endpoints.from + protected[this] def until = endpoints.until + // protected def newSliced(_endpoints: SliceInterval): Transformed[A] = + // self.newSliced(endpoints.recalculate(_endpoints)) + + def foreach[U](f: A => U) { + var index = 0 + for (x <- self) { + if (from <= index) { + if (until <= index) return + f(x) + } + index += 1 + } + } + final override protected[this] def viewIdentifier = "S" + } - trait Mapped[B] extends Transformed[B] with super.Mapped[B] + trait Mapped[B] extends Transformed[B] { + protected[this] val mapping: A => B + def foreach[U](f: B => U) { + for (x <- self) + f(mapping(x)) + } + final override protected[this] def viewIdentifier = "M" + } - trait FlatMapped[B] extends Transformed[B] with super.FlatMapped[B] + trait FlatMapped[B] extends Transformed[B] { + protected[this] val mapping: A => GenTraversableOnce[B] + def foreach[U](f: B => U) { + for (x <- self) + for (y <- mapping(x).seq) + f(y) + } + final override protected[this] def viewIdentifier = "N" + } - trait Appended[B >: A] extends Transformed[B] with super.Appended[B] + trait Appended[B >: A] extends Transformed[B] { + protected[this] val rest: GenTraversable[B] + def foreach[U](f: B => U) { + self foreach f + rest foreach f + } + final override protected[this] def viewIdentifier = "A" + } - trait Filtered extends Transformed[A] with super.Filtered + trait Filtered extends Transformed[A] { + protected[this] val pred: A => Boolean + def foreach[U](f: A => U) { + for (x <- self) + if (pred(x)) f(x) + } + final override protected[this] def viewIdentifier = "F" + } - trait TakenWhile extends Transformed[A] with super.TakenWhile + trait TakenWhile extends Transformed[A] { + protected[this] val pred: A => Boolean + def foreach[U](f: A => U) { + for (x <- self) { + if (!pred(x)) return + f(x) + } + } + final override protected[this] def viewIdentifier = "T" + } - trait DroppedWhile extends Transformed[A] with super.DroppedWhile + trait DroppedWhile extends Transformed[A] { + protected[this] val pred: A => Boolean + def foreach[U](f: A => U) { + var go = false + for (x <- self) { + if (!go && !pred(x)) go = true + if (go) f(x) + } + } + final override protected[this] def viewIdentifier = "D" + } override def ++[B >: A, That](xs: GenTraversableOnce[B])(implicit bf: CanBuildFrom[This, B, That]): That = { newAppended(xs.seq.toTraversable).asInstanceOf[That] @@ -162,7 +244,7 @@ trait TraversableViewLike[+A, // if (b.isInstanceOf[NoBuilder[_]]) newFlatMapped(f).asInstanceOf[That] // else super.flatMap[B, That](f)(bf) } - override def flatten[B](implicit asTraversable: A => /*<:<!!!*/ GenTraversableOnce[B]) = + override def flatten[B](implicit asTraversable: A => /*<:<!!!*/ GenTraversableOnce[B]) = newFlatMapped(asTraversable) private[this] implicit def asThis(xs: Transformed[A]): This = xs.asInstanceOf[This] @@ -209,7 +291,18 @@ trait TraversableViewLike[+A, override def unzip3[A1, A2, A3](implicit asTriple: A => (A1, A2, A3)) = (newMapped(x => asTriple(x)._1), newMapped(x => asTriple(x)._2), newMapped(x => asTriple(x)._3)) // TODO - Performance improvements. - override def toString = viewToString -} + override def filterNot(p: (A) => Boolean): This = + newFiltered(a => !(p(a))) + + override def inits: Iterator[This] = + thisSeq.inits.map(as => newForced(as).asInstanceOf[This]) + + override def tails: Iterator[This] = + thisSeq.tails.map(as => newForced(as).asInstanceOf[This]) + override def tail: This = + // super.tail would also work as it is currently implemented in terms of drop(Int). + if (isEmpty) super.tail else newDropped(1) + override def toString = viewToString +} diff --git a/src/library/scala/collection/concurrent/BasicNode.java b/src/library/scala/collection/concurrent/BasicNode.java index a65d84bbf8..97b8870036 100644 --- a/src/library/scala/collection/concurrent/BasicNode.java +++ b/src/library/scala/collection/concurrent/BasicNode.java @@ -8,13 +8,8 @@ package scala.collection.concurrent; - - - - - public abstract class BasicNode { - + public abstract String string(int lev); - -}
\ No newline at end of file + +} diff --git a/src/library/scala/collection/concurrent/CNodeBase.java b/src/library/scala/collection/concurrent/CNodeBase.java index d6eb29c8df..2fce971b2b 100644 --- a/src/library/scala/collection/concurrent/CNodeBase.java +++ b/src/library/scala/collection/concurrent/CNodeBase.java @@ -8,28 +8,26 @@ package scala.collection.concurrent; - - import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; +abstract class CNodeBase<K, V> extends MainNode<K, V> { + @SuppressWarnings("rawtypes") + public static final AtomicIntegerFieldUpdater<CNodeBase> updater = + AtomicIntegerFieldUpdater.newUpdater(CNodeBase.class, "csize"); -abstract class CNodeBase<K, V> extends MainNode<K, V> { - - public static final AtomicIntegerFieldUpdater<CNodeBase> updater = AtomicIntegerFieldUpdater.newUpdater(CNodeBase.class, "csize"); - public volatile int csize = -1; - + public boolean CAS_SIZE(int oldval, int nval) { return updater.compareAndSet(this, oldval, nval); } - + public void WRITE_SIZE(int nval) { updater.set(this, nval); } - + public int READ_SIZE() { return updater.get(this); } - + }
\ No newline at end of file diff --git a/src/library/scala/collection/concurrent/Gen.java b/src/library/scala/collection/concurrent/Gen.java index 331eeca16b..6019884683 100644 --- a/src/library/scala/collection/concurrent/Gen.java +++ b/src/library/scala/collection/concurrent/Gen.java @@ -8,11 +8,4 @@ package scala.collection.concurrent; - - - - - -final class Gen { -} - +final class Gen {} diff --git a/src/library/scala/collection/concurrent/INodeBase.java b/src/library/scala/collection/concurrent/INodeBase.java index cbe404edf6..2f2d203287 100644 --- a/src/library/scala/collection/concurrent/INodeBase.java +++ b/src/library/scala/collection/concurrent/INodeBase.java @@ -8,28 +8,26 @@ package scala.collection.concurrent; - - import java.util.concurrent.atomic.AtomicReferenceFieldUpdater; +abstract class INodeBase<K, V> extends BasicNode { + @SuppressWarnings("rawtypes") + public static final AtomicReferenceFieldUpdater<INodeBase, MainNode> updater = + AtomicReferenceFieldUpdater.newUpdater(INodeBase.class, MainNode.class, "mainnode"); -abstract class INodeBase<K, V> extends BasicNode { - - public static final AtomicReferenceFieldUpdater<INodeBase, MainNode> updater = AtomicReferenceFieldUpdater.newUpdater(INodeBase.class, MainNode.class, "mainnode"); - public static final Object RESTART = new Object(); - + public volatile MainNode<K, V> mainnode = null; - + public final Gen gen; - + public INodeBase(Gen generation) { gen = generation; } - + public BasicNode prev() { return null; } - + }
\ No newline at end of file diff --git a/src/library/scala/collection/concurrent/MainNode.java b/src/library/scala/collection/concurrent/MainNode.java index ffe535742e..adb9b59a3d 100644 --- a/src/library/scala/collection/concurrent/MainNode.java +++ b/src/library/scala/collection/concurrent/MainNode.java @@ -8,33 +8,32 @@ package scala.collection.concurrent; - - import java.util.concurrent.atomic.AtomicReferenceFieldUpdater; +abstract class MainNode<K, V> extends BasicNode { + @SuppressWarnings("rawtypes") + public static final AtomicReferenceFieldUpdater<MainNode, MainNode> updater = + AtomicReferenceFieldUpdater.newUpdater(MainNode.class, MainNode.class, "prev"); -abstract class MainNode<K, V> extends BasicNode { - - public static final AtomicReferenceFieldUpdater<MainNode, MainNode> updater = AtomicReferenceFieldUpdater.newUpdater(MainNode.class, MainNode.class, "prev"); - public volatile MainNode<K, V> prev = null; - + public abstract int cachedSize(Object ct); - + public boolean CAS_PREV(MainNode<K, V> oldval, MainNode<K, V> nval) { return updater.compareAndSet(this, oldval, nval); } - + public void WRITE_PREV(MainNode<K, V> nval) { updater.set(this, nval); } - + // do we need this? unclear in the javadocs... // apparently not - volatile reads are supposed to be safe // irregardless of whether there are concurrent ARFU updates + @Deprecated @SuppressWarnings("unchecked") public MainNode<K, V> READ_PREV() { return updater.get(this); } - + }
\ No newline at end of file diff --git a/src/library/scala/collection/concurrent/Map.scala b/src/library/scala/collection/concurrent/Map.scala index b2276ce5aa..02e5dd01f5 100644 --- a/src/library/scala/collection/concurrent/Map.scala +++ b/src/library/scala/collection/concurrent/Map.scala @@ -6,7 +6,8 @@ ** |/ ** \* */ -package scala.collection.concurrent +package scala +package collection.concurrent /** A template trait for mutable maps that allow concurrent access. * diff --git a/src/library/scala/collection/concurrent/TrieMap.scala b/src/library/scala/collection/concurrent/TrieMap.scala index 714260fa8a..fccc1d81b9 100644 --- a/src/library/scala/collection/concurrent/TrieMap.scala +++ b/src/library/scala/collection/concurrent/TrieMap.scala @@ -6,7 +6,8 @@ ** |/ ** \* */ -package scala.collection +package scala +package collection package concurrent import java.util.concurrent.atomic._ @@ -41,7 +42,7 @@ private[collection] final class INode[K, V](bn: MainNode[K, V], g: Gen) extends @tailrec private def GCAS_Complete(m: MainNode[K, V], ct: TrieMap[K, V]): MainNode[K, V] = if (m eq null) null else { // complete the GCAS val prev = /*READ*/m.prev - val ctr = ct.readRoot(true) + val ctr = ct.readRoot(abort = true) prev match { case null => @@ -250,7 +251,7 @@ private[collection] final class INode[K, V](bn: MainNode[K, V], g: Gen) extends if (ct.isReadOnly || (startgen eq in.gen)) in.rec_lookup(k, hc, lev + 5, this, startgen, ct) else { if (GCAS(cn, cn.renewed(startgen, ct), ct)) rec_lookup(k, hc, lev, parent, startgen, ct) - else return RESTART // used to be throw RestartException + else RESTART // used to be throw RestartException } case sn: SNode[K, V] => // 2) singleton node if (sn.hc == hc && equal(sn.k, k, ct)) sn.v.asInstanceOf[AnyRef] @@ -428,16 +429,16 @@ extends MainNode[K, V] with KVNode[K, V] { } -private[collection] final class LNode[K, V](final val listmap: ImmutableListMap[K, V]) +private[collection] final class LNode[K, V](final val listmap: immutable.ListMap[K, V]) extends MainNode[K, V] { - def this(k: K, v: V) = this(ImmutableListMap(k -> v)) - def this(k1: K, v1: V, k2: K, v2: V) = this(ImmutableListMap(k1 -> v1, k2 -> v2)) + def this(k: K, v: V) = this(immutable.ListMap(k -> v)) + def this(k1: K, v1: V, k2: K, v2: V) = this(immutable.ListMap(k1 -> v1, k2 -> v2)) def inserted(k: K, v: V) = new LNode(listmap + ((k, v))) def removed(k: K, ct: TrieMap[K, V]): MainNode[K, V] = { val updmap = listmap - k if (updmap.size > 1) new LNode(updmap) else { - val (k, v) = updmap.iterator.next + val (k, v) = updmap.iterator.next() new TNode(k, v, ct.computeHash(k)) // create it tombed so that it gets compressed on subsequent accesses } } @@ -545,7 +546,7 @@ private[collection] final class CNode[K, V](val bitmap: Int, val array: Array[Ba // removed (those existing when the op began) // - if there are only null-i-nodes below, returns null def toCompressed(ct: TrieMap[K, V], lev: Int, gen: Gen) = { - var bmp = bitmap + val bmp = bitmap var i = 0 val arr = array val tmparray = new Array[BasicNode](arr.length) @@ -654,8 +655,8 @@ extends scala.collection.concurrent.Map[K, V] /* internal methods */ private def writeObject(out: java.io.ObjectOutputStream) { - out.writeObject(hashf) - out.writeObject(ef) + out.writeObject(hashingobj) + out.writeObject(equalityobj) val it = iterator while (it.hasNext) { @@ -723,7 +724,7 @@ extends scala.collection.concurrent.Map[K, V] private def RDCSS_ROOT(ov: INode[K, V], expectedmain: MainNode[K, V], nv: INode[K, V]): Boolean = { val desc = RDCSS_Descriptor(ov, expectedmain, nv) if (CAS_ROOT(ov, desc)) { - RDCSS_Complete(false) + RDCSS_Complete(abort = false) /*READ*/desc.committed } else false } @@ -920,8 +921,8 @@ object TrieMap extends MutableMapFactory[TrieMap] { private[collection] class TrieMapIterator[K, V](var level: Int, private var ct: TrieMap[K, V], mustInit: Boolean = true) extends Iterator[(K, V)] { - private var stack = new Array[Array[BasicNode]](7) - private var stackpos = new Array[Int](7) + private val stack = new Array[Array[BasicNode]](7) + private val stackpos = new Array[Int](7) private var depth = -1 private var subiter: Iterator[(K, V)] = null private var current: KVNode[K, V] = null @@ -1030,7 +1031,7 @@ private[collection] class TrieMapIterator[K, V](var level: Int, private var ct: val (arr1, arr2) = stack(d).drop(stackpos(d) + 1).splitAt(rem / 2) stack(d) = arr1 stackpos(d) = -1 - val it = newIterator(level + 1, ct, false) + val it = newIterator(level + 1, ct, _mustInit = false) it.stack(0) = arr2 it.stackpos(0) = -1 it.depth = 0 diff --git a/src/library/scala/collection/convert/DecorateAsJava.scala b/src/library/scala/collection/convert/DecorateAsJava.scala index 87bcae3923..6658b6feea 100644 --- a/src/library/scala/collection/convert/DecorateAsJava.scala +++ b/src/library/scala/collection/convert/DecorateAsJava.scala @@ -6,7 +6,8 @@ ** |/ ** \* */ -package scala.collection +package scala +package collection package convert import java.{ lang => jl, util => ju }, java.util.{ concurrent => juc } @@ -25,7 +26,7 @@ import scala.language.implicitConversions * - `scala.collection.mutable.Buffer` <=> `java.util.List` * - `scala.collection.mutable.Set` <=> `java.util.Set` * - `scala.collection.mutable.Map` <=> `java.util.Map` - * - `scala.collection.mutable.ConcurrentMap` <=> `java.util.concurrent.ConcurrentMap` + * - `scala.collection.mutable.concurrent.Map` <=> `java.util.concurrent.ConcurrentMap` * * In all cases, converting from a source type to a target type and back * again will return the original source object, e.g. @@ -279,26 +280,6 @@ trait DecorateAsJava { /** * Adds an `asJava` method that implicitly converts a Scala mutable - * `ConcurrentMap` to a Java `ConcurrentMap`. - * - * The returned Java `ConcurrentMap` is backed by the provided Scala - * `ConcurrentMap` and any side-effects of using it via the Java interface - * will be visible via the Scala interface and vice versa. - * - * If the Scala `ConcurrentMap` was previously obtained from an implicit or - * explicit call of `asConcurrentMap(java.util.concurrect.ConcurrentMap)` - * then the original Java `ConcurrentMap` will be returned. - * - * @param m The `ConcurrentMap` to be converted. - * @return An object with an `asJava` method that returns a Java - * `ConcurrentMap` view of the argument. - */ - @deprecated("Use `concurrent.Map` instead of `ConcurrentMap`.", "2.10.0") - implicit def asJavaConcurrentMapConverter[A, B](m: mutable.ConcurrentMap[A, B]): AsJava[juc.ConcurrentMap[A, B]] = - new AsJava(asJavaConcurrentMap(m)) - - /** - * Adds an `asJava` method that implicitly converts a Scala mutable * `concurrent.Map` to a Java `ConcurrentMap`. * * The returned Java `ConcurrentMap` is backed by the provided Scala @@ -306,7 +287,7 @@ trait DecorateAsJava { * will be visible via the Scala interface and vice versa. * * If the Scala `concurrent.Map` was previously obtained from an implicit or - * explicit call of `asConcurrentMap(java.util.concurrect.ConcurrentMap)` + * explicit call of `asConcurrentMap(java.util.concurrent.ConcurrentMap)` * then the original Java `ConcurrentMap` will be returned. * * @param m The Scala `concurrent.Map` to be converted. diff --git a/src/library/scala/collection/convert/DecorateAsScala.scala b/src/library/scala/collection/convert/DecorateAsScala.scala index 94847a76e3..c724831c54 100644 --- a/src/library/scala/collection/convert/DecorateAsScala.scala +++ b/src/library/scala/collection/convert/DecorateAsScala.scala @@ -6,7 +6,8 @@ ** |/ ** \* */ -package scala.collection +package scala +package collection package convert import java.{ lang => jl, util => ju }, java.util.{ concurrent => juc } @@ -144,25 +145,6 @@ trait DecorateAsScala { /** * Adds an `asScala` method that implicitly converts a Java `ConcurrentMap` - * to a Scala mutable `ConcurrentMap`. The returned Scala `ConcurrentMap` is - * backed by the provided Java `ConcurrentMap` and any side-effects of using - * it via the Scala interface will be visible via the Java interface and - * vice versa. - * - * If the Java `ConcurrentMap` was previously obtained from an implicit or - * explicit call of `asConcurrentMap(scala.collection.mutable.ConcurrentMap)` - * then the original Scala `ConcurrentMap` will be returned. - * - * @param m The `ConcurrentMap` to be converted. - * @return An object with an `asScala` method that returns a Scala mutable - * `ConcurrentMap` view of the argument. - */ - @deprecated("Use `mapAsScalaConcurrentMapConverter` instead, and use `concurrent.Map` instead of `ConcurrentMap`.", "2.10.0") - def asScalaConcurrentMapConverter[A, B](m: juc.ConcurrentMap[A, B]): AsScala[mutable.ConcurrentMap[A, B]] = - new AsScala(asScalaConcurrentMap(m)) - - /** - * Adds an `asScala` method that implicitly converts a Java `ConcurrentMap` * to a Scala mutable `concurrent.Map`. The returned Scala `concurrent.Map` is * backed by the provided Java `ConcurrentMap` and any side-effects of using * it via the Scala interface will be visible via the Java interface and diff --git a/src/library/scala/collection/convert/Decorators.scala b/src/library/scala/collection/convert/Decorators.scala index e2c46c1e4f..d232fa04e1 100644 --- a/src/library/scala/collection/convert/Decorators.scala +++ b/src/library/scala/collection/convert/Decorators.scala @@ -6,10 +6,11 @@ ** |/ ** \* */ -package scala.collection +package scala +package collection package convert -import java.{ lang => jl, util => ju }, java.util.{ concurrent => juc } +import java.{ util => ju } private[collection] trait Decorators { /** Generic class containing the `asJava` converter method */ diff --git a/src/library/scala/collection/convert/WrapAsJava.scala b/src/library/scala/collection/convert/WrapAsJava.scala index 5e6126a7cf..9916fe9843 100644 --- a/src/library/scala/collection/convert/WrapAsJava.scala +++ b/src/library/scala/collection/convert/WrapAsJava.scala @@ -6,7 +6,8 @@ ** |/ ** \* */ -package scala.collection +package scala +package collection package convert import java.{ lang => jl, util => ju }, java.util.{ concurrent => juc } @@ -235,27 +236,6 @@ trait WrapAsJava { } /** - * Implicitly converts a Scala mutable `ConcurrentMap` to a Java - * `ConcurrentMap`. - * - * The returned Java `ConcurrentMap` is backed by the provided Scala - * `ConcurrentMap` and any side-effects of using it via the Java interface - * will be visible via the Scala interface and vice versa. - * - * If the Scala `ConcurrentMap` was previously obtained from an implicit or - * explicit call of `asScalaConcurrentMap(java.util.concurrect.ConcurrentMap)` - * then the original Java ConcurrentMap will be returned. - * - * @param m The `ConcurrentMap` to be converted. - * @return A Java `ConcurrentMap` view of the argument. - */ - @deprecated("Use `concurrent.Map` instead of `ConcurrentMap`.", "2.10.0") - implicit def asJavaConcurrentMap[A, B](m: mutable.ConcurrentMap[A, B]): juc.ConcurrentMap[A, B] = m match { - case JConcurrentMapDeprecatedWrapper(wrapped) => wrapped - case _ => new ConcurrentMapDeprecatedWrapper(m) - } - - /** * Implicitly converts a Scala mutable `concurrent.Map` to a Java * `ConcurrentMap`. * @@ -264,7 +244,7 @@ trait WrapAsJava { * will be visible via the Scala interface and vice versa. * * If the Scala `concurrent.Map` was previously obtained from an implicit or - * explicit call of `mapAsScalaConcurrentMap(java.util.concurrect.ConcurrentMap)` + * explicit call of `mapAsScalaConcurrentMap(java.util.concurrent.ConcurrentMap)` * then the original Java ConcurrentMap will be returned. * * @param m The Scala `concurrent.Map` to be converted. @@ -277,11 +257,3 @@ trait WrapAsJava { } object WrapAsJava extends WrapAsJava { } - - - - - - - - diff --git a/src/library/scala/collection/convert/WrapAsScala.scala b/src/library/scala/collection/convert/WrapAsScala.scala index ffcca62291..d4ab451b0d 100644 --- a/src/library/scala/collection/convert/WrapAsScala.scala +++ b/src/library/scala/collection/convert/WrapAsScala.scala @@ -6,36 +6,14 @@ ** |/ ** \* */ -package scala.collection +package scala +package collection package convert import java.{ lang => jl, util => ju }, java.util.{ concurrent => juc } import scala.language.implicitConversions -trait LowPriorityWrapAsScala { - this: WrapAsScala => - - import Wrappers._ - - /** - * Implicitly converts a Java ConcurrentMap to a Scala mutable ConcurrentMap. - * The returned Scala ConcurrentMap is backed by the provided Java - * ConcurrentMap and any side-effects of using it via the Scala interface will - * be visible via the Java interface and vice versa. - * - * If the Java ConcurrentMap was previously obtained from an implicit or - * explicit call of `asConcurrentMap(scala.collection.mutable.ConcurrentMap)` - * then the original Scala ConcurrentMap will be returned. - * - * @param m The ConcurrentMap to be converted. - * @return A Scala mutable ConcurrentMap view of the argument. - */ - @deprecated("Use `mapAsScalaConcurrentMap` instead, and use `concurrent.Map` instead of `ConcurrentMap`.", "2.10.0") - implicit def mapAsScalaDeprecatedConcurrentMap[A, B](m: juc.ConcurrentMap[A, B]): mutable.ConcurrentMap[A, B] = - asScalaConcurrentMap(m) -} - -trait WrapAsScala extends LowPriorityWrapAsScala { +trait WrapAsScala { import Wrappers._ /** * Implicitly converts a Java `Iterator` to a Scala `Iterator`. @@ -178,25 +156,6 @@ trait WrapAsScala extends LowPriorityWrapAsScala { * @param m The ConcurrentMap to be converted. * @return A Scala mutable ConcurrentMap view of the argument. */ - @deprecated("Use `mapAsScalaConcurrentMap` instead, and use `concurrent.Map` instead of `ConcurrentMap`.", "2.10.0") - def asScalaConcurrentMap[A, B](m: juc.ConcurrentMap[A, B]): mutable.ConcurrentMap[A, B] = m match { - case cmw: ConcurrentMapDeprecatedWrapper[a, b] => cmw.underlying - case _ => new JConcurrentMapDeprecatedWrapper(m) - } - - /** - * Implicitly converts a Java ConcurrentMap to a Scala mutable ConcurrentMap. - * The returned Scala ConcurrentMap is backed by the provided Java - * ConcurrentMap and any side-effects of using it via the Scala interface will - * be visible via the Java interface and vice versa. - * - * If the Java ConcurrentMap was previously obtained from an implicit or - * explicit call of `asConcurrentMap(scala.collection.mutable.ConcurrentMap)` - * then the original Scala ConcurrentMap will be returned. - * - * @param m The ConcurrentMap to be converted. - * @return A Scala mutable ConcurrentMap view of the argument. - */ implicit def mapAsScalaConcurrentMap[A, B](m: juc.ConcurrentMap[A, B]): concurrent.Map[A, B] = m match { case cmw: ConcurrentMapWrapper[a, b] => cmw.underlying case _ => new JConcurrentMapWrapper(m) diff --git a/src/library/scala/collection/convert/Wrappers.scala b/src/library/scala/collection/convert/Wrappers.scala index 20add3365d..7d1d6b3781 100644 --- a/src/library/scala/collection/convert/Wrappers.scala +++ b/src/library/scala/collection/convert/Wrappers.scala @@ -6,7 +6,8 @@ ** |/ ** \* */ -package scala.collection +package scala +package collection package convert import java.{ lang => jl, util => ju }, java.util.{ concurrent => juc } @@ -27,9 +28,9 @@ private[collection] trait Wrappers { case class IteratorWrapper[A](underlying: Iterator[A]) extends ju.Iterator[A] with ju.Enumeration[A] { def hasNext = underlying.hasNext - def next() = underlying.next + def next() = underlying.next() def hasMoreElements = underlying.hasNext - def nextElement() = underlying.next + def nextElement() = underlying.next() def remove() = throw new UnsupportedOperationException } @@ -81,7 +82,7 @@ private[collection] trait Wrappers { override def remove(i: Int) = underlying remove i } - case class JListWrapper[A](val underlying: ju.List[A]) extends mutable.AbstractBuffer[A] with mutable.Buffer[A] { + case class JListWrapper[A](underlying: ju.List[A]) extends mutable.AbstractBuffer[A] with mutable.Buffer[A] { def length = underlying.size override def isEmpty = underlying.isEmpty override def iterator: Iterator[A] = underlying.iterator @@ -101,14 +102,20 @@ private[collection] trait Wrappers { override def clone(): JListWrapper[A] = JListWrapper(new ju.ArrayList[A](underlying)) } + // Note various overrides to avoid performance gotchas. class SetWrapper[A](underlying: Set[A]) extends ju.AbstractSet[A] { self => + override def contains(o: Object): Boolean = { + try { underlying.contains(o.asInstanceOf[A]) } + catch { case cce: ClassCastException => false } + } + override def isEmpty = underlying.isEmpty def size = underlying.size def iterator = new ju.Iterator[A] { val ui = underlying.iterator var prev: Option[A] = None def hasNext = ui.hasNext - def next = { val e = ui.next; prev = Some(e); e } + def next = { val e = ui.next(); prev = Some(e); e } def remove = prev match { case Some(e) => underlying match { @@ -180,14 +187,14 @@ private[collection] trait Wrappers { def hasNext = ui.hasNext def next() = { - val (k, v) = ui.next + val (k, v) = ui.next() prev = Some(k) new ju.Map.Entry[A, B] { import scala.util.hashing.byteswap32 def getKey = k def getValue = v def setValue(v1 : B) = self.put(k, v1) - override def hashCode = byteswap32(k.hashCode) + (byteswap32(v.hashCode) << 16) + override def hashCode = byteswap32(k.##) + (byteswap32(v.##) << 16) override def equals(other: Any) = other match { case e: ju.Map.Entry[_, _] => k == e.getKey && v == e.getValue case _ => false @@ -211,6 +218,15 @@ private[collection] trait Wrappers { } } } + + override def containsKey(key: AnyRef): Boolean = try { + // Note: Subclass of collection.Map with specific key type may redirect generic + // contains to specific contains, which will throw a ClassCastException if the + // wrong type is passed. This is why we need a type cast to A inside a try/catch. + underlying.contains(key.asInstanceOf[A]) + } catch { + case ex: ClassCastException => false + } } case class MutableMapWrapper[A, B](underlying: mutable.Map[A, B]) extends MapWrapper[A, B](underlying) { @@ -272,32 +288,10 @@ private[collection] trait Wrappers { override def empty: Repr = null.asInstanceOf[Repr] } - case class JMapWrapper[A, B](val underlying : ju.Map[A, B]) extends mutable.AbstractMap[A, B] with JMapWrapperLike[A, B, JMapWrapper[A, B]] { + case class JMapWrapper[A, B](underlying : ju.Map[A, B]) extends mutable.AbstractMap[A, B] with JMapWrapperLike[A, B, JMapWrapper[A, B]] { override def empty = JMapWrapper(new ju.HashMap[A, B]) } - class ConcurrentMapDeprecatedWrapper[A, B](override val underlying: mutable.ConcurrentMap[A, B]) extends MutableMapWrapper[A, B](underlying) with juc.ConcurrentMap[A, B] { - - def putIfAbsent(k: A, v: B) = underlying.putIfAbsent(k, v) match { - case Some(v) => v - case None => null.asInstanceOf[B] - } - - def remove(k: AnyRef, v: AnyRef) = try { - underlying.remove(k.asInstanceOf[A], v.asInstanceOf[B]) - } catch { - case ex: ClassCastException => - false - } - - def replace(k: A, v: B): B = underlying.replace(k, v) match { - case Some(v) => v - case None => null.asInstanceOf[B] - } - - def replace(k: A, oldval: B, newval: B) = underlying.replace(k, oldval, newval) - } - class ConcurrentMapWrapper[A, B](override val underlying: concurrent.Map[A, B]) extends MutableMapWrapper[A, B](underlying) with juc.ConcurrentMap[A, B] { def putIfAbsent(k: A, v: B) = underlying.putIfAbsent(k, v) match { @@ -320,32 +314,7 @@ private[collection] trait Wrappers { def replace(k: A, oldval: B, newval: B) = underlying.replace(k, oldval, newval) } - case class JConcurrentMapDeprecatedWrapper[A, B](val underlying: juc.ConcurrentMap[A, B]) extends mutable.AbstractMap[A, B] with JMapWrapperLike[A, B, JConcurrentMapDeprecatedWrapper[A, B]] with mutable.ConcurrentMap[A, B] { - override def get(k: A) = { - val v = underlying get k - if (v != null) Some(v) - else None - } - - override def empty = new JConcurrentMapDeprecatedWrapper(new juc.ConcurrentHashMap[A, B]) - - def putIfAbsent(k: A, v: B): Option[B] = { - val r = underlying.putIfAbsent(k, v) - if (r != null) Some(r) else None - } - - def remove(k: A, v: B): Boolean = underlying.remove(k, v) - - def replace(k: A, v: B): Option[B] = { - val prev = underlying.replace(k, v) - if (prev != null) Some(prev) else None - } - - def replace(k: A, oldvalue: B, newvalue: B): Boolean = - underlying.replace(k, oldvalue, newvalue) - } - - case class JConcurrentMapWrapper[A, B](val underlying: juc.ConcurrentMap[A, B]) extends mutable.AbstractMap[A, B] with JMapWrapperLike[A, B, JConcurrentMapWrapper[A, B]] with concurrent.Map[A, B] { + case class JConcurrentMapWrapper[A, B](underlying: juc.ConcurrentMap[A, B]) extends mutable.AbstractMap[A, B] with JMapWrapperLike[A, B, JConcurrentMapWrapper[A, B]] with concurrent.Map[A, B] { override def get(k: A) = { val v = underlying get k if (v != null) Some(v) diff --git a/src/library/scala/collection/convert/package.scala b/src/library/scala/collection/convert/package.scala index ea66101aca..13970f9a3e 100644 --- a/src/library/scala/collection/convert/package.scala +++ b/src/library/scala/collection/convert/package.scala @@ -6,7 +6,8 @@ ** |/ ** \* */ -package scala.collection +package scala +package collection package object convert { val decorateAsJava = new DecorateAsJava { } diff --git a/src/library/scala/collection/generic/BitOperations.scala b/src/library/scala/collection/generic/BitOperations.scala index c45ebcf982..d430ece2f5 100644 --- a/src/library/scala/collection/generic/BitOperations.scala +++ b/src/library/scala/collection/generic/BitOperations.scala @@ -6,7 +6,8 @@ ** |/ ** \* */ -package scala.collection +package scala +package collection package generic /** Some bit operations. diff --git a/src/library/scala/collection/generic/BitSetFactory.scala b/src/library/scala/collection/generic/BitSetFactory.scala index 46e2d29612..2e3aae31ac 100644 --- a/src/library/scala/collection/generic/BitSetFactory.scala +++ b/src/library/scala/collection/generic/BitSetFactory.scala @@ -8,7 +8,8 @@ -package scala.collection +package scala +package collection package generic import scala.collection._ diff --git a/src/library/scala/collection/generic/CanBuildFrom.scala b/src/library/scala/collection/generic/CanBuildFrom.scala index 73fd4fc026..24e5b2a1dd 100644 --- a/src/library/scala/collection/generic/CanBuildFrom.scala +++ b/src/library/scala/collection/generic/CanBuildFrom.scala @@ -7,7 +7,8 @@ \* */ -package scala.collection +package scala +package collection package generic import mutable.Builder diff --git a/src/library/scala/collection/generic/CanCombineFrom.scala b/src/library/scala/collection/generic/CanCombineFrom.scala index 9ca3332ba0..7f70b4580a 100644 --- a/src/library/scala/collection/generic/CanCombineFrom.scala +++ b/src/library/scala/collection/generic/CanCombineFrom.scala @@ -6,7 +6,8 @@ ** |/ ** \* */ -package scala.collection +package scala +package collection package generic import scala.collection.parallel._ diff --git a/src/library/scala/collection/generic/ClassTagTraversableFactory.scala b/src/library/scala/collection/generic/ClassTagTraversableFactory.scala index 85cdbd7276..e3db40123d 100644 --- a/src/library/scala/collection/generic/ClassTagTraversableFactory.scala +++ b/src/library/scala/collection/generic/ClassTagTraversableFactory.scala @@ -6,7 +6,8 @@ ** |/ ** \* */ -package scala.collection +package scala +package collection package generic import scala.language.higherKinds diff --git a/src/library/scala/collection/generic/Clearable.scala b/src/library/scala/collection/generic/Clearable.scala index a04ecb2a68..3c496051c4 100644 --- a/src/library/scala/collection/generic/Clearable.scala +++ b/src/library/scala/collection/generic/Clearable.scala @@ -6,7 +6,8 @@ ** |/ ** \* */ -package scala.collection +package scala +package collection package generic /** This trait forms part of collections that can be cleared diff --git a/src/library/scala/collection/generic/FilterMonadic.scala b/src/library/scala/collection/generic/FilterMonadic.scala index e21f0be898..8aefbdb926 100755 --- a/src/library/scala/collection/generic/FilterMonadic.scala +++ b/src/library/scala/collection/generic/FilterMonadic.scala @@ -6,8 +6,9 @@ ** |/ ** \* */ -package scala.collection.generic - +package scala +package collection +package generic /** A template trait that contains just the `map`, `flatMap`, `foreach` and `withFilter` methods * of trait `TraversableLike`. diff --git a/src/library/scala/collection/generic/GenMapFactory.scala b/src/library/scala/collection/generic/GenMapFactory.scala index e869bba51a..ae3150115f 100644 --- a/src/library/scala/collection/generic/GenMapFactory.scala +++ b/src/library/scala/collection/generic/GenMapFactory.scala @@ -6,7 +6,8 @@ ** |/ ** \* */ -package scala.collection +package scala +package collection package generic import mutable.{Builder, MapBuilder} @@ -44,7 +45,7 @@ abstract class GenMapFactory[CC[A, B] <: GenMap[A, B] with GenMapLike[A, B, CC[A * @tparam B the type of the associated values * @return a new $coll consisting key/value pairs given by `elems`. */ - def apply[A, B](elems: (A, B)*): CC[A, B] = (newBuilder[A, B] ++= elems).result + def apply[A, B](elems: (A, B)*): CC[A, B] = (newBuilder[A, B] ++= elems).result() /** The default builder for $Coll objects. * @tparam A the type of the keys diff --git a/src/library/scala/collection/generic/GenSeqFactory.scala b/src/library/scala/collection/generic/GenSeqFactory.scala index dd375c567c..6afbb2e2fb 100644 --- a/src/library/scala/collection/generic/GenSeqFactory.scala +++ b/src/library/scala/collection/generic/GenSeqFactory.scala @@ -8,7 +8,8 @@ -package scala.collection +package scala +package collection package generic import scala.language.higherKinds diff --git a/src/library/scala/collection/generic/GenSetFactory.scala b/src/library/scala/collection/generic/GenSetFactory.scala index 9774805cf8..800f66eb53 100644 --- a/src/library/scala/collection/generic/GenSetFactory.scala +++ b/src/library/scala/collection/generic/GenSetFactory.scala @@ -8,7 +8,8 @@ -package scala.collection +package scala +package collection package generic import mutable.Builder diff --git a/src/library/scala/collection/generic/GenTraversableFactory.scala b/src/library/scala/collection/generic/GenTraversableFactory.scala index 2d3f7e609b..2092c0c5f5 100644 --- a/src/library/scala/collection/generic/GenTraversableFactory.scala +++ b/src/library/scala/collection/generic/GenTraversableFactory.scala @@ -7,7 +7,8 @@ \* */ -package scala.collection +package scala +package collection package generic import scala.language.higherKinds @@ -38,12 +39,10 @@ import scala.language.higherKinds abstract class GenTraversableFactory[CC[X] <: GenTraversable[X] with GenericTraversableTemplate[X, CC]] extends GenericCompanion[CC] { - // A default implementation of GenericCanBuildFrom which can be cast - // to whatever is desired. - private class ReusableCBF extends GenericCanBuildFrom[Nothing] { + private[this] val ReusableCBFInstance: GenericCanBuildFrom[Nothing] = new GenericCanBuildFrom[Nothing] { override def apply() = newBuilder[Nothing] } - lazy val ReusableCBF: GenericCanBuildFrom[Nothing] = new ReusableCBF + def ReusableCBF: GenericCanBuildFrom[Nothing] = ReusableCBFInstance /** A generic implementation of the `CanBuildFrom` trait, which forwards * all calls to `apply(from)` to the `genericBuilder` method of @@ -75,7 +74,7 @@ extends GenericCompanion[CC] { b.sizeHint(xss.map(_.size).sum) for (xs <- xss.seq) b ++= xs - b.result + b.result() } /** Produces a $coll containing the results of some element computation a number of times. @@ -91,7 +90,7 @@ extends GenericCompanion[CC] { b += elem i += 1 } - b.result + b.result() } /** Produces a two-dimensional $coll containing the results of some element computation a number of times. @@ -149,7 +148,7 @@ extends GenericCompanion[CC] { b += f(i) i += 1 } - b.result + b.result() } /** Produces a two-dimensional $coll containing values of a given function over ranges of integer values starting from 0. @@ -218,13 +217,13 @@ extends GenericCompanion[CC] { if (step == zero) throw new IllegalArgumentException("zero step") val b = newBuilder[T] - b sizeHint immutable.NumericRange.count(start, end, step, false) + b sizeHint immutable.NumericRange.count(start, end, step, isInclusive = false) var i = start while (if (step < zero) end < i else i < end) { b += i i += step } - b.result + b.result() } /** Produces a $coll containing repeated applications of a function to a start value. @@ -248,7 +247,6 @@ extends GenericCompanion[CC] { b += acc } } - b.result + b.result() } } - diff --git a/src/library/scala/collection/generic/GenericClassTagCompanion.scala b/src/library/scala/collection/generic/GenericClassTagCompanion.scala index 76c12d118e..a8ac2bf738 100644 --- a/src/library/scala/collection/generic/GenericClassTagCompanion.scala +++ b/src/library/scala/collection/generic/GenericClassTagCompanion.scala @@ -6,7 +6,8 @@ ** |/ ** \* */ -package scala.collection +package scala +package collection package generic import mutable.Builder @@ -23,11 +24,11 @@ abstract class GenericClassTagCompanion[+CC[X] <: Traversable[X]] { def newBuilder[A](implicit ord: ClassTag[A]): Builder[A, CC[A]] - def empty[A: ClassTag]: CC[A] = newBuilder[A].result + def empty[A: ClassTag]: CC[A] = newBuilder[A].result() def apply[A](elems: A*)(implicit ord: ClassTag[A]): CC[A] = { val b = newBuilder[A] b ++= elems - b.result + b.result() } } diff --git a/src/library/scala/collection/generic/GenericClassTagTraversableTemplate.scala b/src/library/scala/collection/generic/GenericClassTagTraversableTemplate.scala index f327710848..090cd729a4 100644 --- a/src/library/scala/collection/generic/GenericClassTagTraversableTemplate.scala +++ b/src/library/scala/collection/generic/GenericClassTagTraversableTemplate.scala @@ -6,7 +6,8 @@ ** |/ ** \* */ -package scala.collection +package scala +package collection package generic import mutable.Builder diff --git a/src/library/scala/collection/generic/GenericCompanion.scala b/src/library/scala/collection/generic/GenericCompanion.scala index b966ce51db..67d0a9c7f7 100644 --- a/src/library/scala/collection/generic/GenericCompanion.scala +++ b/src/library/scala/collection/generic/GenericCompanion.scala @@ -6,7 +6,8 @@ ** |/ ** \* */ -package scala.collection +package scala +package collection package generic import mutable.Builder @@ -34,7 +35,7 @@ abstract class GenericCompanion[+CC[X] <: GenTraversable[X]] { /** An empty collection of type `$Coll[A]` * @tparam A the type of the ${coll}'s elements */ - def empty[A]: CC[A] = newBuilder[A].result + def empty[A]: CC[A] = newBuilder[A].result() /** Creates a $coll with the specified elements. * @tparam A the type of the ${coll}'s elements @@ -46,7 +47,7 @@ abstract class GenericCompanion[+CC[X] <: GenTraversable[X]] { else { val b = newBuilder[A] b ++= elems - b.result + b.result() } } } diff --git a/src/library/scala/collection/generic/GenericOrderedCompanion.scala b/src/library/scala/collection/generic/GenericOrderedCompanion.scala index 094912c75a..5b328bff6c 100644 --- a/src/library/scala/collection/generic/GenericOrderedCompanion.scala +++ b/src/library/scala/collection/generic/GenericOrderedCompanion.scala @@ -6,7 +6,8 @@ ** |/ ** \* */ -package scala.collection +package scala +package collection package generic import mutable.Builder @@ -23,12 +24,12 @@ abstract class GenericOrderedCompanion[+CC[X] <: Traversable[X]] { def newBuilder[A](implicit ord: Ordering[A]): Builder[A, CC[A]] - def empty[A: Ordering]: CC[A] = newBuilder[A].result + def empty[A: Ordering]: CC[A] = newBuilder[A].result() def apply[A](elems: A*)(implicit ord: Ordering[A]): CC[A] = { val b = newBuilder[A] b ++= elems - b.result + b.result() } } diff --git a/src/library/scala/collection/generic/GenericOrderedTraversableTemplate.scala b/src/library/scala/collection/generic/GenericOrderedTraversableTemplate.scala index a624e8ca93..c1a41ce7c4 100644 --- a/src/library/scala/collection/generic/GenericOrderedTraversableTemplate.scala +++ b/src/library/scala/collection/generic/GenericOrderedTraversableTemplate.scala @@ -8,7 +8,8 @@ -package scala.collection +package scala +package collection package generic import mutable.Builder diff --git a/src/library/scala/collection/generic/GenericParCompanion.scala b/src/library/scala/collection/generic/GenericParCompanion.scala index bb39461e7e..432b9135f8 100644 --- a/src/library/scala/collection/generic/GenericParCompanion.scala +++ b/src/library/scala/collection/generic/GenericParCompanion.scala @@ -6,7 +6,9 @@ ** |/ ** \* */ -package scala.collection.generic +package scala +package collection +package generic import scala.collection.parallel.Combiner import scala.collection.parallel.ParIterable diff --git a/src/library/scala/collection/generic/GenericParTemplate.scala b/src/library/scala/collection/generic/GenericParTemplate.scala index 94c76630d6..b9b7043270 100644 --- a/src/library/scala/collection/generic/GenericParTemplate.scala +++ b/src/library/scala/collection/generic/GenericParTemplate.scala @@ -6,7 +6,9 @@ ** |/ ** \* */ -package scala.collection.generic +package scala +package collection +package generic import scala.collection.parallel.Combiner import scala.collection.parallel.ParIterable diff --git a/src/library/scala/collection/generic/GenericSeqCompanion.scala b/src/library/scala/collection/generic/GenericSeqCompanion.scala index 8b2f8a0fcb..fd1e18a029 100644 --- a/src/library/scala/collection/generic/GenericSeqCompanion.scala +++ b/src/library/scala/collection/generic/GenericSeqCompanion.scala @@ -6,8 +6,8 @@ ** |/ ** \* */ - -package scala.collection +package scala +package collection package generic import scala.language.higherKinds diff --git a/src/library/scala/collection/generic/GenericSetTemplate.scala b/src/library/scala/collection/generic/GenericSetTemplate.scala index ecfdcffbc5..2cadd14948 100644 --- a/src/library/scala/collection/generic/GenericSetTemplate.scala +++ b/src/library/scala/collection/generic/GenericSetTemplate.scala @@ -6,7 +6,8 @@ ** |/ ** \* */ -package scala.collection +package scala +package collection package generic import scala.language.higherKinds /** diff --git a/src/library/scala/collection/generic/GenericTraversableTemplate.scala b/src/library/scala/collection/generic/GenericTraversableTemplate.scala index f7a8a9aa88..cd48cd23f4 100644 --- a/src/library/scala/collection/generic/GenericTraversableTemplate.scala +++ b/src/library/scala/collection/generic/GenericTraversableTemplate.scala @@ -8,7 +8,8 @@ -package scala.collection +package scala +package collection package generic import mutable.Builder @@ -73,11 +74,20 @@ trait GenericTraversableTemplate[+A, +CC[X] <: GenTraversable[X]] extends HasNew /** Converts this $coll of pairs into two collections of the first and second * half of each pair. * + * {{{ + * val xs = $Coll( + * (1, "one"), + * (2, "two"), + * (3, "three")).unzip + * // xs == ($Coll(1, 2, 3), + * // $Coll(one, two, three)) + * }}} + * * @tparam A1 the type of the first half of the element pairs * @tparam A2 the type of the second half of the element pairs * @param asPair an implicit conversion which asserts that the element type * of this $coll is a pair. - * @return a pair ${coll}s, containing the first, respectively second + * @return a pair of ${coll}s, containing the first, respectively second * half of each element pair of this $coll. */ def unzip[A1, A2](implicit asPair: A => (A1, A2)): (CC[A1], CC[A2]) = { @@ -88,18 +98,28 @@ trait GenericTraversableTemplate[+A, +CC[X] <: GenTraversable[X]] extends HasNew b1 += x b2 += y } - (b1.result, b2.result) + (b1.result(), b2.result()) } /** Converts this $coll of triples into three collections of the first, second, * and third element of each triple. * + * {{{ + * val xs = $Coll( + * (1, "one", '1'), + * (2, "two", '2'), + * (3, "three", '3')).unzip3 + * // xs == ($Coll(1, 2, 3), + * // $Coll(one, two, three), + * // $Coll(1, 2, 3)) + * }}} + * * @tparam A1 the type of the first member of the element triples * @tparam A2 the type of the second member of the element triples * @tparam A3 the type of the third member of the element triples * @param asTriple an implicit conversion which asserts that the element type * of this $coll is a triple. - * @return a triple ${coll}s, containing the first, second, respectively + * @return a triple of ${coll}s, containing the first, second, respectively * third member of each element triple of this $coll. */ def unzip3[A1, A2, A3](implicit asTriple: A => (A1, A2, A3)): (CC[A1], CC[A2], CC[A3]) = { @@ -113,7 +133,7 @@ trait GenericTraversableTemplate[+A, +CC[X] <: GenTraversable[X]] extends HasNew b2 += y b3 += z } - (b1.result, b2.result, b3.result) + (b1.result(), b2.result(), b3.result()) } /** Converts this $coll of traversable collections into @@ -133,10 +153,16 @@ trait GenericTraversableTemplate[+A, +CC[X] <: GenTraversable[X]] extends HasNew * static type of $coll. For example: * * {{{ - * val xs = List(Set(1, 2, 3), Set(1, 2, 3)) + * val xs = List( + * Set(1, 2, 3), + * Set(1, 2, 3) + * ).flatten * // xs == List(1, 2, 3, 1, 2, 3) * - * val ys = Set(List(1, 2, 3), List(3, 2, 1)) + * val ys = Set( + * List(1, 2, 3), + * List(3, 2, 1) + * ).flatten * // ys == Set(1, 2, 3) * }}} */ @@ -144,12 +170,33 @@ trait GenericTraversableTemplate[+A, +CC[X] <: GenTraversable[X]] extends HasNew val b = genericBuilder[B] for (xs <- sequential) b ++= asTraversable(xs).seq - b.result + b.result() } /** Transposes this $coll of traversable collections into * a $coll of ${coll}s. * + * The resulting collection's type will be guided by the + * static type of $coll. For example: + * + * {{{ + * val xs = List( + * Set(1, 2, 3), + * Set(4, 5, 6)).transpose + * // xs == List( + * // List(1, 4), + * // List(2, 5), + * // List(3, 6)) + * + * val ys = Vector( + * List(1, 2, 3), + * List(4, 5, 6)).transpose + * // ys == Vector( + * // Vector(1, 4), + * // Vector(2, 5), + * // Vector(3, 6)) + * }}} + * * @tparam B the type of the elements of each traversable collection. * @param asTraversable an implicit conversion which asserts that the * element type of this $coll is a `Traversable`. @@ -161,7 +208,7 @@ trait GenericTraversableTemplate[+A, +CC[X] <: GenTraversable[X]] extends HasNew @migration("`transpose` throws an `IllegalArgumentException` if collections are not uniformly sized.", "2.9.0") def transpose[B](implicit asTraversable: A => /*<:<!!!*/ GenTraversableOnce[B]): CC[CC[B] @uncheckedVariance] = { if (isEmpty) - return genericBuilder[CC[B]].result + return genericBuilder[CC[B]].result() def fail = throw new IllegalArgumentException("transpose requires all collections have the same size") @@ -179,7 +226,7 @@ trait GenericTraversableTemplate[+A, +CC[X] <: GenTraversable[X]] extends HasNew } val bb = genericBuilder[CC[B]] for (b <- bs) bb += b.result - bb.result + bb.result() } } diff --git a/src/library/scala/collection/generic/Growable.scala b/src/library/scala/collection/generic/Growable.scala index cb75212e3d..a223c0c8a8 100644 --- a/src/library/scala/collection/generic/Growable.scala +++ b/src/library/scala/collection/generic/Growable.scala @@ -6,10 +6,12 @@ ** |/ ** \* */ - -package scala.collection +package scala +package collection package generic +import scala.annotation.tailrec + /** This trait forms part of collections that can be augmented * using a `+=` operator and that can be cleared of all elements using * a `clear` method. @@ -45,7 +47,19 @@ trait Growable[-A] extends Clearable { * @param xs the TraversableOnce producing the elements to $add. * @return the $coll itself. */ - def ++=(xs: TraversableOnce[A]): this.type = { xs.seq foreach += ; this } + def ++=(xs: TraversableOnce[A]): this.type = { + @tailrec def loop(xs: scala.collection.LinearSeq[A]) { + if (xs.nonEmpty) { + this += xs.head + loop(xs.tail) + } + } + xs match { + case xs: scala.collection.LinearSeq[_] => loop(xs) + case xs => xs foreach += + } + this + } /** Clears the $coll's contents. After this operation, the * $coll is empty. diff --git a/src/library/scala/collection/generic/HasNewBuilder.scala b/src/library/scala/collection/generic/HasNewBuilder.scala index 1a981b487f..aa0ce6698d 100755 --- a/src/library/scala/collection/generic/HasNewBuilder.scala +++ b/src/library/scala/collection/generic/HasNewBuilder.scala @@ -5,7 +5,8 @@ ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** \* */ -package scala.collection +package scala +package collection package generic import mutable.Builder diff --git a/src/library/scala/collection/generic/HasNewCombiner.scala b/src/library/scala/collection/generic/HasNewCombiner.scala index 1ecfba19af..99a0722c3d 100644 --- a/src/library/scala/collection/generic/HasNewCombiner.scala +++ b/src/library/scala/collection/generic/HasNewCombiner.scala @@ -6,7 +6,9 @@ ** |/ ** \* */ -package scala.collection.generic +package scala +package collection +package generic import scala.collection.parallel.Combiner diff --git a/src/library/scala/collection/generic/ImmutableMapFactory.scala b/src/library/scala/collection/generic/ImmutableMapFactory.scala index 4ce50a31f9..7d857bf1b4 100644 --- a/src/library/scala/collection/generic/ImmutableMapFactory.scala +++ b/src/library/scala/collection/generic/ImmutableMapFactory.scala @@ -7,7 +7,8 @@ \* */ -package scala.collection +package scala +package collection package generic import scala.language.higherKinds diff --git a/src/library/scala/collection/generic/ImmutableSetFactory.scala b/src/library/scala/collection/generic/ImmutableSetFactory.scala index 2e960e670d..a72caf2633 100644 --- a/src/library/scala/collection/generic/ImmutableSetFactory.scala +++ b/src/library/scala/collection/generic/ImmutableSetFactory.scala @@ -6,7 +6,8 @@ ** |/ ** \* */ -package scala.collection +package scala +package collection package generic import mutable.{ Builder, SetBuilder } @@ -14,6 +15,7 @@ import scala.language.higherKinds abstract class ImmutableSetFactory[CC[X] <: immutable.Set[X] with SetLike[X, CC[X]]] extends SetFactory[CC] { - + private[collection] def emptyInstance: CC[Any] + override def empty[A] = emptyInstance.asInstanceOf[CC[A]] def newBuilder[A]: Builder[A, CC[A]] = new SetBuilder[A, CC[A]](empty[A]) } diff --git a/src/library/scala/collection/generic/ImmutableSortedMapFactory.scala b/src/library/scala/collection/generic/ImmutableSortedMapFactory.scala index 7743fc2281..730e58a527 100644 --- a/src/library/scala/collection/generic/ImmutableSortedMapFactory.scala +++ b/src/library/scala/collection/generic/ImmutableSortedMapFactory.scala @@ -8,7 +8,8 @@ -package scala.collection +package scala +package collection package generic import scala.language.higherKinds diff --git a/src/library/scala/collection/generic/ImmutableSortedSetFactory.scala b/src/library/scala/collection/generic/ImmutableSortedSetFactory.scala index 9914557b51..1fd4a8c99d 100644 --- a/src/library/scala/collection/generic/ImmutableSortedSetFactory.scala +++ b/src/library/scala/collection/generic/ImmutableSortedSetFactory.scala @@ -8,7 +8,8 @@ -package scala.collection +package scala +package collection package generic import scala.language.higherKinds diff --git a/src/library/scala/ScalaObject.scala b/src/library/scala/collection/generic/IndexedSeqFactory.scala index f67dc3a6c5..ddc0141aa9 100644 --- a/src/library/scala/ScalaObject.scala +++ b/src/library/scala/collection/generic/IndexedSeqFactory.scala @@ -7,10 +7,16 @@ \* */ package scala +package collection +package generic -/** Until scala 2.10.0 this marker trait was added to - * scala-compiled classes. Now it only exists for backward - * compatibility. +import language.higherKinds + +/** A template for companion objects of IndexedSeq and subclasses thereof. + * + * @since 2.11 */ -@deprecated("ScalaObject will be removed", "2.10.0") -trait ScalaObject +abstract class IndexedSeqFactory[CC[X] <: IndexedSeq[X] with GenericTraversableTemplate[X, CC]] extends SeqFactory[CC] { + override def ReusableCBF: GenericCanBuildFrom[Nothing] = + scala.collection.IndexedSeq.ReusableCBF.asInstanceOf[GenericCanBuildFrom[Nothing]] +} diff --git a/src/library/scala/collection/generic/IsSeqLike.scala b/src/library/scala/collection/generic/IsSeqLike.scala new file mode 100644 index 0000000000..4c857ad1bb --- /dev/null +++ b/src/library/scala/collection/generic/IsSeqLike.scala @@ -0,0 +1,58 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +package scala +package collection +package generic + +/** Type class witnessing that a collection representation type `Repr` has + * elements of type `A` and has a conversion to `SeqLike[A, Repr]`. + * + * This type enables simple enrichment of `Seq`s with extension methods which + * can make full use of the mechanics of the Scala collections framework in + * their implementation. + * + * Example usage: + * {{{ + * class FilterMapImpl[A, Repr](val r: SeqLike[A, Repr]) { + * final def filterMap[B, That](f: A => Option[B])(implicit cbf: CanBuildFrom[Repr, B, That]): That = + * r.flatMap(f(_)) + * } + * implicit def filterMap[Repr, A](r: Repr)(implicit fr: IsSeqLike[Repr]): FilterMapImpl[fr.A,Repr] = + * new FilterMapImpl(fr.conversion(r)) + * + * val l = List(1, 2, 3, 4, 5) + * List(1, 2, 3, 4, 5) filterMap (i => if(i % 2 == 0) Some(i) else None) + * // == List(2, 4) + * }}} + * + * @see [[scala.collection.Seq]] + * @see [[scala.collection.generic.IsTraversableLike]] + */ +trait IsSeqLike[Repr] { + /** The type of elements we can traverse over. */ + type A + /** A conversion from the representation type `Repr` to a `SeqLike[A,Repr]`. */ + val conversion: Repr => SeqLike[A, Repr] +} + +object IsSeqLike { + import scala.language.higherKinds + + implicit val stringRepr: IsSeqLike[String] { type A = Char } = + new IsSeqLike[String] { + type A = Char + val conversion = implicitly[String => SeqLike[Char, String]] + } + + implicit def seqLikeRepr[C[_], A0](implicit conv: C[A0] => SeqLike[A0,C[A0]]): IsSeqLike[C[A0]] { type A = A0 } = + new IsSeqLike[C[A0]] { + type A = A0 + val conversion = conv + } +} diff --git a/src/library/scala/collection/generic/IsTraversableLike.scala b/src/library/scala/collection/generic/IsTraversableLike.scala index c70772d8f9..22cef555cc 100644 --- a/src/library/scala/collection/generic/IsTraversableLike.scala +++ b/src/library/scala/collection/generic/IsTraversableLike.scala @@ -6,7 +6,8 @@ ** |/ ** \* */ -package scala.collection +package scala +package collection package generic /** A trait which can be used to avoid code duplication when defining extension diff --git a/src/library/scala/collection/generic/IsTraversableOnce.scala b/src/library/scala/collection/generic/IsTraversableOnce.scala index bb5404c92d..3ee586ae63 100644 --- a/src/library/scala/collection/generic/IsTraversableOnce.scala +++ b/src/library/scala/collection/generic/IsTraversableOnce.scala @@ -6,7 +6,8 @@ ** |/ ** \* */ -package scala.collection +package scala +package collection package generic /** Type class witnessing that a collection representation type `Repr` has diff --git a/src/library/scala/collection/generic/IterableForwarder.scala b/src/library/scala/collection/generic/IterableForwarder.scala index 90ebcace84..7387dbe667 100644 --- a/src/library/scala/collection/generic/IterableForwarder.scala +++ b/src/library/scala/collection/generic/IterableForwarder.scala @@ -6,13 +6,12 @@ ** |/ ** \* */ +package scala +package collection +package generic - -package scala.collection.generic import scala.collection._ -import scala.collection.mutable.Buffer - /** This trait implements a forwarder for iterable objects. It forwards * all calls to a different iterable object, except for * @@ -27,6 +26,7 @@ import scala.collection.mutable.Buffer * @version 2.8 * @since 2.8 */ +@deprecated("Forwarding is inherently unreliable since it is not automated and methods can be forgotten.", "2.11.0") trait IterableForwarder[+A] extends Iterable[A] with TraversableForwarder[A] { /** The iterable object to which calls are forwarded */ diff --git a/src/library/scala/collection/generic/MapFactory.scala b/src/library/scala/collection/generic/MapFactory.scala index 565850bee2..b9f3d4b010 100644 --- a/src/library/scala/collection/generic/MapFactory.scala +++ b/src/library/scala/collection/generic/MapFactory.scala @@ -6,7 +6,8 @@ ** |/ ** \* */ -package scala.collection +package scala +package collection package generic diff --git a/src/library/scala/collection/generic/MutableMapFactory.scala b/src/library/scala/collection/generic/MutableMapFactory.scala index ac139cc80c..14c5b6bac3 100644 --- a/src/library/scala/collection/generic/MutableMapFactory.scala +++ b/src/library/scala/collection/generic/MutableMapFactory.scala @@ -8,7 +8,8 @@ -package scala.collection +package scala +package collection package generic import mutable.Builder diff --git a/src/library/scala/collection/generic/MutableSetFactory.scala b/src/library/scala/collection/generic/MutableSetFactory.scala index 9c69d53608..63944657fc 100644 --- a/src/library/scala/collection/generic/MutableSetFactory.scala +++ b/src/library/scala/collection/generic/MutableSetFactory.scala @@ -6,7 +6,8 @@ ** |/ ** \* */ -package scala.collection +package scala +package collection package generic import mutable.{ Builder, GrowingBuilder } diff --git a/src/library/scala/collection/generic/MutableSortedSetFactory.scala b/src/library/scala/collection/generic/MutableSortedSetFactory.scala index b9be83c3c4..0339a523e9 100644 --- a/src/library/scala/collection/generic/MutableSortedSetFactory.scala +++ b/src/library/scala/collection/generic/MutableSortedSetFactory.scala @@ -6,7 +6,8 @@ ** |/ ** \* */ -package scala.collection +package scala +package collection package generic import scala.collection.mutable.{ Builder, GrowingBuilder } diff --git a/src/library/scala/collection/generic/OrderedTraversableFactory.scala b/src/library/scala/collection/generic/OrderedTraversableFactory.scala index a2de108721..7657aff2aa 100644 --- a/src/library/scala/collection/generic/OrderedTraversableFactory.scala +++ b/src/library/scala/collection/generic/OrderedTraversableFactory.scala @@ -7,7 +7,8 @@ \* */ -package scala.collection +package scala +package collection package generic import scala.language.higherKinds diff --git a/src/library/scala/collection/generic/ParFactory.scala b/src/library/scala/collection/generic/ParFactory.scala index bb88d26dec..4486cea419 100644 --- a/src/library/scala/collection/generic/ParFactory.scala +++ b/src/library/scala/collection/generic/ParFactory.scala @@ -6,7 +6,9 @@ ** |/ ** \* */ -package scala.collection.generic +package scala +package collection +package generic import scala.collection.parallel.ParIterable import scala.collection.parallel.Combiner @@ -35,8 +37,3 @@ extends GenTraversableFactory[CC] override def apply() = newBuilder[A] } } - - - - - diff --git a/src/library/scala/collection/generic/ParMapFactory.scala b/src/library/scala/collection/generic/ParMapFactory.scala index 0a6b08ae34..70797c83e2 100644 --- a/src/library/scala/collection/generic/ParMapFactory.scala +++ b/src/library/scala/collection/generic/ParMapFactory.scala @@ -6,7 +6,9 @@ ** |/ ** \* */ -package scala.collection.generic +package scala +package collection +package generic import scala.collection.parallel.ParMap import scala.collection.parallel.ParMapLike diff --git a/src/library/scala/collection/generic/ParSetFactory.scala b/src/library/scala/collection/generic/ParSetFactory.scala index 3727ab89f7..4320635ae6 100644 --- a/src/library/scala/collection/generic/ParSetFactory.scala +++ b/src/library/scala/collection/generic/ParSetFactory.scala @@ -6,7 +6,9 @@ ** |/ ** \* */ -package scala.collection.generic +package scala +package collection +package generic import scala.collection.mutable.Builder import scala.collection.parallel.Combiner diff --git a/src/library/scala/collection/generic/SeqFactory.scala b/src/library/scala/collection/generic/SeqFactory.scala index a66074741a..35cce11a79 100644 --- a/src/library/scala/collection/generic/SeqFactory.scala +++ b/src/library/scala/collection/generic/SeqFactory.scala @@ -8,7 +8,8 @@ -package scala.collection +package scala +package collection package generic import scala.language.higherKinds diff --git a/src/library/scala/collection/generic/SeqForwarder.scala b/src/library/scala/collection/generic/SeqForwarder.scala index e8b15ec450..e21e2ea016 100644 --- a/src/library/scala/collection/generic/SeqForwarder.scala +++ b/src/library/scala/collection/generic/SeqForwarder.scala @@ -6,7 +6,9 @@ ** |/ ** \* */ -package scala.collection.generic +package scala +package collection +package generic import scala.collection._ import scala.collection.immutable.Range @@ -23,6 +25,7 @@ import scala.collection.immutable.Range * @version 2.8 * @since 2.8 */ +@deprecated("Forwarding is inherently unreliable since it is not automated and new methods can be forgotten.", "2.11.0") trait SeqForwarder[+A] extends Seq[A] with IterableForwarder[A] { protected override def underlying: Seq[A] @@ -50,7 +53,7 @@ trait SeqForwarder[+A] extends Seq[A] with IterableForwarder[A] { override def lastIndexOfSlice[B >: A](that: GenSeq[B]): Int = underlying lastIndexOfSlice that override def lastIndexOfSlice[B >: A](that: GenSeq[B], end: Int): Int = underlying.lastIndexOfSlice(that, end) override def containsSlice[B](that: GenSeq[B]): Boolean = underlying containsSlice that - override def contains(elem: Any): Boolean = underlying contains elem + override def contains[A1 >: A](elem: A1): Boolean = underlying contains elem override def corresponds[B](that: GenSeq[B])(p: (A,B) => Boolean): Boolean = underlying.corresponds(that)(p) override def indices: Range = underlying.indices } diff --git a/src/library/scala/collection/generic/SetFactory.scala b/src/library/scala/collection/generic/SetFactory.scala index e9bbde92f3..fcd8d00c18 100644 --- a/src/library/scala/collection/generic/SetFactory.scala +++ b/src/library/scala/collection/generic/SetFactory.scala @@ -8,7 +8,8 @@ -package scala.collection +package scala +package collection package generic import mutable.Builder diff --git a/src/library/scala/collection/generic/Shrinkable.scala b/src/library/scala/collection/generic/Shrinkable.scala index b00048fd5d..dea5bb7217 100644 --- a/src/library/scala/collection/generic/Shrinkable.scala +++ b/src/library/scala/collection/generic/Shrinkable.scala @@ -6,8 +6,8 @@ ** |/ ** \* */ - -package scala.collection +package scala +package collection package generic /** This trait forms part of collections that can be reduced @@ -46,9 +46,5 @@ trait Shrinkable[-A] { * @param xs the iterator producing the elements to remove. * @return the $coll itself */ - def --=(xs: TraversableOnce[A]): this.type = { xs.seq foreach -= ; this } + def --=(xs: TraversableOnce[A]): this.type = { xs foreach -= ; this } } - - - - diff --git a/src/library/scala/collection/generic/Signalling.scala b/src/library/scala/collection/generic/Signalling.scala index 498db7f8fa..021d289c9d 100644 --- a/src/library/scala/collection/generic/Signalling.scala +++ b/src/library/scala/collection/generic/Signalling.scala @@ -6,15 +6,12 @@ ** |/ ** \* */ -package scala.collection.generic - +package scala +package collection +package generic import java.util.concurrent.atomic.AtomicInteger - - - - /** * A message interface serves as a unique interface to the * part of the collection capable of receiving messages from @@ -95,7 +92,6 @@ trait Signalling { def tag: Int } - /** * This signalling implementation returns default values and ignores received signals. */ @@ -108,13 +104,11 @@ class DefaultSignalling extends Signalling with VolatileAbort { def tag = -1 } - /** * An object that returns default values and ignores received signals. */ object IdleSignalling extends DefaultSignalling - /** * A mixin trait that implements abort flag behaviour using volatile variables. */ @@ -124,7 +118,6 @@ trait VolatileAbort extends Signalling { override def abort() = abortflag = true } - /** * A mixin trait that implements index flag behaviour using atomic integers. * The `setIndex` operation is wait-free, while conditional set operations `setIndexIfGreater` @@ -140,7 +133,7 @@ trait AtomicIndexFlag extends Signalling { val old = intflag.get if (f <= old) loop = false else if (intflag.compareAndSet(old, f)) loop = false - } while (loop); + } while (loop) } abstract override def setIndexFlagIfLesser(f: Int) = { var loop = true @@ -148,11 +141,10 @@ trait AtomicIndexFlag extends Signalling { val old = intflag.get if (f >= old) loop = false else if (intflag.compareAndSet(old, f)) loop = false - } while (loop); + } while (loop) } } - /** * An implementation of the signalling interface using delegates. */ @@ -163,7 +155,7 @@ trait DelegatedSignalling extends Signalling { var signalDelegate: Signalling def isAborted = signalDelegate.isAborted - def abort() = signalDelegate.abort + def abort() = signalDelegate.abort() def indexFlag = signalDelegate.indexFlag def setIndexFlag(f: Int) = signalDelegate.setIndexFlag(f) @@ -173,25 +165,12 @@ trait DelegatedSignalling extends Signalling { def tag = signalDelegate.tag } - /** * Class implementing delegated signalling. */ class DelegatedContext(var signalDelegate: Signalling) extends DelegatedSignalling - /** * Class implementing delegated signalling, but having its own distinct `tag`. */ class TaggedDelegatedContext(deleg: Signalling, override val tag: Int) extends DelegatedContext(deleg) - - - - - - - - - - - diff --git a/src/library/scala/collection/generic/Sizing.scala b/src/library/scala/collection/generic/Sizing.scala index 1191259b3a..73584ce82e 100644 --- a/src/library/scala/collection/generic/Sizing.scala +++ b/src/library/scala/collection/generic/Sizing.scala @@ -6,7 +6,9 @@ ** |/ ** \* */ -package scala.collection.generic +package scala +package collection +package generic /** A trait for objects which have a size. */ diff --git a/src/library/scala/collection/generic/SliceInterval.scala b/src/library/scala/collection/generic/SliceInterval.scala index 244e960454..82acdd1371 100644 --- a/src/library/scala/collection/generic/SliceInterval.scala +++ b/src/library/scala/collection/generic/SliceInterval.scala @@ -6,7 +6,8 @@ ** |/ ** \* */ -package scala.collection +package scala +package collection package generic /** A container for the endpoints of a collection slice. diff --git a/src/library/scala/collection/generic/Sorted.scala b/src/library/scala/collection/generic/Sorted.scala index f962b26bd3..a0b0e1318b 100644 --- a/src/library/scala/collection/generic/Sorted.scala +++ b/src/library/scala/collection/generic/Sorted.scala @@ -6,7 +6,8 @@ ** |/ ** \* */ -package scala.collection +package scala +package collection package generic /** Any collection (including maps) whose keys (or elements) are ordered. @@ -61,7 +62,8 @@ trait Sorted[K, +This <: Sorted[K, This]] { /** Creates a ranged projection of this collection with both a lower-bound * and an upper-bound. * - * @param from The upper-bound (exclusive) of the ranged projection. + * @param from The lower-bound (inclusive) of the ranged projection. + * @param until The upper-bound (exclusive) of the ranged projection. */ def range(from: K, until: K): This = rangeImpl(Some(from), Some(until)) @@ -71,28 +73,40 @@ trait Sorted[K, +This <: Sorted[K, This]] { def to(to: K): This = { val i = keySet.from(to).iterator if (i.isEmpty) return repr - val next = i.next + val next = i.next() if (compare(next, to) == 0) if (i.isEmpty) repr - else until(i.next) + else until(i.next()) else until(next) } + /** + * Creates an iterator over all the keys(or elements) contained in this + * collection greater than or equal to `start` + * according to the ordering of this collection. x.keysIteratorFrom(y) + * is equivalent to but often more efficient than + * x.from(y).keysIterator. + * + * @param start The lower bound (inclusive) + * on the keys to be returned + */ + def keysIteratorFrom(start: K): Iterator[K] + protected def hasAll(j: Iterator[K]): Boolean = { val i = keySet.iterator if (i.isEmpty) return j.isEmpty - var in = i.next; + var in = i.next() while (j.hasNext) { - val jn = j.next; + val jn = j.next() while ({ - val n = compare(jn, in); - if (n == 0) false; - else if (n < 0) return false; - else if (!i.hasNext) return false; - else true; - }) in = i.next; + val n = compare(jn, in) + if (n == 0) false + else if (n < 0) return false + else if (!i.hasNext) return false + else true + }) in = i.next() } true } diff --git a/src/library/scala/collection/generic/SortedMapFactory.scala b/src/library/scala/collection/generic/SortedMapFactory.scala index 17201b0f7a..afa11e9ab1 100644 --- a/src/library/scala/collection/generic/SortedMapFactory.scala +++ b/src/library/scala/collection/generic/SortedMapFactory.scala @@ -8,7 +8,8 @@ -package scala.collection +package scala +package collection package generic import mutable.{Builder, MapBuilder} @@ -24,7 +25,7 @@ abstract class SortedMapFactory[CC[A, B] <: SortedMap[A, B] with SortedMapLike[A def empty[A, B](implicit ord: Ordering[A]): CC[A, B] - def apply[A, B](elems: (A, B)*)(implicit ord: Ordering[A]): CC[A, B] = (newBuilder[A, B](ord) ++= elems).result + def apply[A, B](elems: (A, B)*)(implicit ord: Ordering[A]): CC[A, B] = (newBuilder[A, B](ord) ++= elems).result() def newBuilder[A, B](implicit ord: Ordering[A]): Builder[(A, B), CC[A, B]] = new MapBuilder[A, B, CC[A, B]](empty(ord)) diff --git a/src/library/scala/collection/generic/SortedSetFactory.scala b/src/library/scala/collection/generic/SortedSetFactory.scala index 08bca04e42..c734830e0b 100644 --- a/src/library/scala/collection/generic/SortedSetFactory.scala +++ b/src/library/scala/collection/generic/SortedSetFactory.scala @@ -8,7 +8,8 @@ -package scala.collection +package scala +package collection package generic import mutable.{Builder, SetBuilder} @@ -23,11 +24,11 @@ abstract class SortedSetFactory[CC[A] <: SortedSet[A] with SortedSetLike[A, CC[A def empty[A](implicit ord: Ordering[A]): CC[A] - def apply[A](elems: A*)(implicit ord: Ordering[A]): CC[A] = (newBuilder[A](ord) ++= elems).result + def apply[A](elems: A*)(implicit ord: Ordering[A]): CC[A] = (newBuilder[A](ord) ++= elems).result() def newBuilder[A](implicit ord: Ordering[A]): Builder[A, CC[A]] = new SetBuilder[A, CC[A]](empty) - implicit def newCanBuildFrom[A](implicit ord : Ordering[A]) : CanBuildFrom[Coll, A, CC[A]] = new SortedSetCanBuildFrom()(ord); + implicit def newCanBuildFrom[A](implicit ord : Ordering[A]) : CanBuildFrom[Coll, A, CC[A]] = new SortedSetCanBuildFrom()(ord) class SortedSetCanBuildFrom[A](implicit ord: Ordering[A]) extends CanBuildFrom[Coll, A, CC[A]] { def apply(from: Coll) = newBuilder[A](ord) diff --git a/src/library/scala/collection/generic/Subtractable.scala b/src/library/scala/collection/generic/Subtractable.scala index e0fe07a0a4..32a9000296 100644 --- a/src/library/scala/collection/generic/Subtractable.scala +++ b/src/library/scala/collection/generic/Subtractable.scala @@ -7,7 +7,8 @@ \* */ -package scala.collection +package scala +package collection package generic diff --git a/src/library/scala/collection/generic/TraversableFactory.scala b/src/library/scala/collection/generic/TraversableFactory.scala index 5d1c9d17e2..ad6d8fd198 100644 --- a/src/library/scala/collection/generic/TraversableFactory.scala +++ b/src/library/scala/collection/generic/TraversableFactory.scala @@ -7,7 +7,8 @@ \* */ -package scala.collection +package scala +package collection package generic import scala.language.higherKinds diff --git a/src/library/scala/collection/generic/TraversableForwarder.scala b/src/library/scala/collection/generic/TraversableForwarder.scala index 2662018feb..1d7974f7a4 100644 --- a/src/library/scala/collection/generic/TraversableForwarder.scala +++ b/src/library/scala/collection/generic/TraversableForwarder.scala @@ -6,7 +6,9 @@ ** |/ ** \* */ -package scala.collection.generic +package scala +package collection +package generic import scala.collection._ import mutable.{ Buffer, StringBuilder } @@ -25,6 +27,7 @@ import scala.reflect.ClassTag * @version 2.8 * @since 2.8 */ +@deprecated("Forwarding is inherently unreliable since it is not automated and new methods can be forgotten.", "2.11.0") trait TraversableForwarder[+A] extends Traversable[A] { /** The traversable object to which calls are forwarded. */ protected def underlying: Traversable[A] diff --git a/src/library/scala/collection/generic/package.scala b/src/library/scala/collection/generic/package.scala index dd47b7ace6..1beb4a8599 100644 --- a/src/library/scala/collection/generic/package.scala +++ b/src/library/scala/collection/generic/package.scala @@ -1,4 +1,5 @@ -package scala.collection +package scala +package collection import generic.CanBuildFrom import scala.language.higherKinds diff --git a/src/library/scala/collection/immutable/BitSet.scala b/src/library/scala/collection/immutable/BitSet.scala index ed3630edc1..70543aa3a6 100644 --- a/src/library/scala/collection/immutable/BitSet.scala +++ b/src/library/scala/collection/immutable/BitSet.scala @@ -8,7 +8,8 @@ -package scala.collection +package scala +package collection package immutable import generic._ @@ -31,9 +32,6 @@ abstract class BitSet extends scala.collection.AbstractSet[Int] with Serializable { override def empty = BitSet.empty - @deprecated("Use BitSet.fromBitMask[NoCopy] instead of fromArray", "2.10.0") - def fromArray(elems: Array[Long]): BitSet = fromBitMaskNoCopy(elems) - protected def fromBitMaskNoCopy(elems: Array[Long]): BitSet = BitSet.fromBitMaskNoCopy(elems) /** Update word at index `idx`; enlarge set if `idx` outside range of set. @@ -74,7 +72,7 @@ object BitSet extends BitSetFactory[BitSet] { def newBuilder: Builder[Int, BitSet] = new Builder[Int, BitSet] { private[this] val b = new mutable.BitSet def += (x: Int) = { b += x; this } - def clear() = b.clear + def clear() = b.clear() def result() = b.toImmutable } @@ -82,10 +80,6 @@ object BitSet extends BitSetFactory[BitSet] { implicit def canBuildFrom: CanBuildFrom[BitSet, Int, BitSet] = bitsetCanBuildFrom /** A bitset containing all the bits in an array */ - @deprecated("Use fromBitMask[NoCopy] instead of fromArray", "2.10.0") - def fromArray(elems: Array[Long]): BitSet = fromBitMaskNoCopy(elems) - - /** A bitset containing all the bits in an array */ def fromBitMask(elems: Array[Long]): BitSet = { val len = elems.length if (len == 0) empty diff --git a/src/library/scala/collection/immutable/DefaultMap.scala b/src/library/scala/collection/immutable/DefaultMap.scala index 4a0503adfd..e9b277b9c4 100755 --- a/src/library/scala/collection/immutable/DefaultMap.scala +++ b/src/library/scala/collection/immutable/DefaultMap.scala @@ -6,13 +6,10 @@ ** |/ ** \* */ - - -package scala.collection +package scala +package collection package immutable -import generic._ - /** A default map which implements the `+` and `-` * methods of maps. It does so using the default builder for * maps defined in the `Map` object. @@ -42,24 +39,14 @@ trait DefaultMap[A, +B] extends Map[A, B] { self => val b = Map.newBuilder[A, B1] b ++= this b += ((kv._1, kv._2)) - b.result + b.result() } /** A default implementation which creates a new immutable map. */ override def - (key: A): Map[A, B] = { val b = newBuilder - for (kv <- this.seq ; if kv._1 != key) b += kv - b.result + for (kv <- this ; if kv._1 != key) b += kv + b.result() } } - - - - - - - - - - diff --git a/src/library/scala/collection/immutable/GenIterable.scala.disabled b/src/library/scala/collection/immutable/GenIterable.scala.disabled deleted file mode 100644 index d34f7fd856..0000000000 --- a/src/library/scala/collection/immutable/GenIterable.scala.disabled +++ /dev/null @@ -1,37 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala.collection -package immutable - - -import generic._ -import mutable.Builder - - -/** A base trait for iterable collections that can be mutated. - * - * $possiblyparinfo - * - * $iterableInfo - */ -trait GenIterable[+A] extends GenTraversable[A] - with scala.collection.GenIterable[A] - with scala.collection.GenIterableLike[A, GenIterable[A]] -// with GenericTraversableTemplate[A, GenIterable] -{ - def seq: Iterable[A] - //override def companion: GenericCompanion[GenIterable] = GenIterable -} - - -// object GenIterable extends TraversableFactory[GenIterable] { -// implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, GenIterable[A]] = ReusableCBF.asInstanceOf[GenericCanBuildFrom[A]] -// def newBuilder[A]: Builder[A, GenIterable[A]] = Iterable.newBuilder -// } - diff --git a/src/library/scala/collection/immutable/GenMap.scala.disabled b/src/library/scala/collection/immutable/GenMap.scala.disabled deleted file mode 100644 index 73557a4a66..0000000000 --- a/src/library/scala/collection/immutable/GenMap.scala.disabled +++ /dev/null @@ -1,36 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala.collection -package immutable - -import generic._ - - -/** A base trait for maps that can be mutated. - * $possiblyparinfo - * $mapNote - * $mapTags - * @since 1.0 - * @author Matthias Zenger - */ -trait GenMap[A, +B] -extends GenIterable[(A, B)] - with scala.collection.GenMap[A, B] - with scala.collection.GenMapLike[A, B, GenMap[A, B]] -{ - def seq: Map[A, B] -} - - -// object GenMap extends MapFactory[GenMap] { -// def empty[A, B]: Map[A, B] = Map.empty - -// /** $mapCanBuildFromInfo */ -// implicit def canBuildFrom[A, B]: CanBuildFrom[Coll, (A, B), GenMap[A, B]] = new MapCanBuildFrom[A, B] -// } diff --git a/src/library/scala/collection/immutable/GenSeq.scala.disabled b/src/library/scala/collection/immutable/GenSeq.scala.disabled deleted file mode 100644 index 713529f3db..0000000000 --- a/src/library/scala/collection/immutable/GenSeq.scala.disabled +++ /dev/null @@ -1,49 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - - -package scala.collection -package immutable - - -import generic._ -import mutable.Builder - - -/** A subtrait of `collection.GenSeq` which represents sequences - * that can be mutated. - * - * $possiblyparinfo - * - * $seqInfo - * - * The class adds an `update` method to `collection.Seq`. - * - * @define Coll `mutable.Seq` - * @define coll mutable sequence - */ -trait GenSeq[+A] extends GenIterable[A] - with scala.collection.GenSeq[A] - with scala.collection.GenSeqLike[A, GenSeq[A]] -// with GenericTraversableTemplate[A, GenSeq] -{ - def seq: Seq[A] - //override def companion: GenericCompanion[GenSeq] = GenSeq -} - - -// object GenSeq extends SeqFactory[GenSeq] { -// implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, GenSeq[A]] = ReusableCBF.asInstanceOf[GenericCanBuildFrom[A]] -// def newBuilder[A]: Builder[A, GenSeq[A]] = Seq.newBuilder -// } - - - - - diff --git a/src/library/scala/collection/immutable/GenSet.scala.disabled b/src/library/scala/collection/immutable/GenSet.scala.disabled deleted file mode 100644 index 56bd2738fd..0000000000 --- a/src/library/scala/collection/immutable/GenSet.scala.disabled +++ /dev/null @@ -1,43 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - - -package scala.collection -package immutable - - -import generic._ -import mutable.Builder - - -/** A generic trait for mutable sets. - * - * $possiblyparinfo - * $setNote - * $setTags - * - * @since 1.0 - * @author Matthias Zenger - * @define Coll `mutable.Set` - * @define coll mutable set - */ -trait GenSet[A] extends GenIterable[A] - with scala.collection.GenSet[A] - with scala.collection.GenSetLike[A, GenSet[A]] -// with GenericSetTemplate[A, GenSet] -{ - //override def companion: GenericCompanion[GenSet] = GenSet - def seq: Set[A] -} - - -// object GenSet extends TraversableFactory[GenSet] { -// implicit def canBuildFrom[A] = ReusableCBF.asInstanceOf[GenericCanBuildFrom[A]] -// def newBuilder[A] = Set.newBuilder -// } diff --git a/src/library/scala/collection/immutable/GenTraversable.scala.disabled b/src/library/scala/collection/immutable/GenTraversable.scala.disabled deleted file mode 100644 index e5b609f9ed..0000000000 --- a/src/library/scala/collection/immutable/GenTraversable.scala.disabled +++ /dev/null @@ -1,41 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - - -package scala.collection -package immutable - - -import generic._ -import mutable.Builder - - -/** A trait for traversable collections that can be mutated. - * - * $possiblyparinfo - * - * $traversableInfo - * @define mutability mutable - */ -trait GenTraversable[+A] extends scala.collection.GenTraversable[A] - with scala.collection.GenTraversableLike[A, GenTraversable[A]] -// with GenericTraversableTemplate[A, GenTraversable] - with Mutable -{ - def seq: Traversable[A] - //override def companion: GenericCompanion[GenTraversable] = GenTraversable -} - - -// object GenTraversable extends TraversableFactory[GenTraversable] { -// implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, GenTraversable[A]] = ReusableCBF.asInstanceOf[GenericCanBuildFrom[A]] -// def newBuilder[A]: Builder[A, GenTraversable[A]] = Traversable.newBuilder -// } - - diff --git a/src/library/scala/collection/immutable/HashMap.scala b/src/library/scala/collection/immutable/HashMap.scala index 84416a62d2..3b3e65ea61 100644 --- a/src/library/scala/collection/immutable/HashMap.scala +++ b/src/library/scala/collection/immutable/HashMap.scala @@ -33,12 +33,15 @@ import parallel.immutable.ParHashMap * @define willNotTerminateInf */ @SerialVersionUID(2L) +@deprecatedInheritance("The implementation details of immutable hash maps make inheriting from them unwise.", "2.11.0") class HashMap[A, +B] extends AbstractMap[A, B] with Map[A, B] with MapLike[A, B, HashMap[A, B]] with Serializable with CustomParallelizable[(A, B), ParHashMap[A, B]] { + import HashMap.{nullToEmpty, bufferSize} + override def size: Int = 0 override def empty = HashMap.empty[A, B] @@ -58,11 +61,22 @@ class HashMap[A, +B] extends AbstractMap[A, B] override def + [B1 >: B] (elem1: (A, B1), elem2: (A, B1), elems: (A, B1) *): HashMap[A, B1] = this + elem1 + elem2 ++ elems - // TODO: optimize (might be able to use mutable updates) def - (key: A): HashMap[A, B] = removed0(key, computeHash(key), 0) + override def filter(p: ((A, B)) => Boolean) = { + val buffer = new Array[HashMap[A, B]](bufferSize(size)) + nullToEmpty(filter0(p, false, 0, buffer, 0)) + } + + override def filterNot(p: ((A, B)) => Boolean) = { + val buffer = new Array[HashMap[A, B]](bufferSize(size)) + nullToEmpty(filter0(p, true, 0, buffer, 0)) + } + + protected def filter0(p: ((A, B)) => Boolean, negate: Boolean, level: Int, buffer: Array[HashMap[A, B @uV]], offset0: Int): HashMap[A, B] = null + protected def elemHashCode(key: A) = key.## protected final def improve(hcode: Int) = { @@ -87,9 +101,6 @@ class HashMap[A, +B] extends AbstractMap[A, B] def split: Seq[HashMap[A, B]] = Seq(this) - @deprecated("Use the `merged` method instead.", "2.10.0") - def merge[B1 >: B](that: HashMap[A, B1], mergef: MergeFunction[A, B1] = null): HashMap[A, B1] = merge0(that, 0, liftMerger(mergef)) - /** Creates a new map which is the merge of this and the argument hash map. * * Uses the specified collision resolution function if two keys are the same. @@ -170,8 +181,6 @@ object HashMap extends ImmutableMapFactory[HashMap] with BitOperations.Int { } } - // TODO: add HashMap2, HashMap3, ... - class HashMap1[A,+B](private[collection] val key: A, private[collection] val hash: Int, private[collection] val value: (B @uV), private[collection] var kv: (A,B @uV)) extends HashMap[A,B] { override def size = 1 @@ -182,21 +191,6 @@ object HashMap extends ImmutableMapFactory[HashMap] with BitOperations.Int { override def get0(key: A, hash: Int, level: Int): Option[B] = if (hash == this.hash && key == this.key) Some(value) else None - // override def updated0[B1 >: B](key: A, hash: Int, level: Int, value: B1, kv: (A, B1)): HashMap[A, B1] = - // if (hash == this.hash && key == this.key) new HashMap1(key, hash, value, kv) - // else { - // var thatindex = (hash >>> level) & 0x1f - // var thisindex = (this.hash >>> level) & 0x1f - // if (hash != this.hash) { - // --new HashTrieMap[A,B1](level+5, this, new HashMap1(key, hash, value, kv)) - // val m = new HashTrieMap[A,B1](0,new Array[HashMap[A,B1]](0),0) // TODO: could save array alloc - // m.updated0(this.key, this.hash, level, this.value, this.kv).updated0(key, hash, level, value, kv) TODO and it will - // } else { - // 32-bit hash collision (rare, but not impossible) - // new HashMapCollision1(hash, ListMap.empty.updated(this.key,this.value).updated(key,value)) - // } - // } - private[collection] override def updated0[B1 >: B](key: A, hash: Int, level: Int, value: B1, kv: (A, B1), merger: Merger[A, B1]): HashMap[A, B1] = if (hash == this.hash && key == this.key ) { if (merger eq null) { @@ -220,6 +214,9 @@ object HashMap extends ImmutableMapFactory[HashMap] with BitOperations.Int { override def removed0(key: A, hash: Int, level: Int): HashMap[A, B] = if (hash == this.hash && key == this.key) HashMap.empty[A,B] else this + override protected def filter0(p: ((A, B)) => Boolean, negate: Boolean, level: Int, buffer: Array[HashMap[A, B @uV]], offset0: Int): HashMap[A, B] = + if (negate ^ p(ensurePair)) this else null + override def iterator: Iterator[(A,B)] = Iterator(ensurePair) override def foreach[U](f: ((A, B)) => U): Unit = f(ensurePair) // this method may be called multiple times in a multithreaded environment, but that's ok @@ -250,15 +247,34 @@ object HashMap extends ImmutableMapFactory[HashMap] with BitOperations.Int { override def removed0(key: A, hash: Int, level: Int): HashMap[A, B] = if (hash == this.hash) { val kvs1 = kvs - key - if (kvs1.isEmpty) - HashMap.empty[A,B] - else if(kvs1.tail.isEmpty) { - val kv = kvs1.head - new HashMap1[A,B](kv._1,hash,kv._2,kv) - } else - new HashMapCollision1(hash, kvs1) + kvs1.size match { + case 0 => + HashMap.empty[A,B] + case 1 => + val kv = kvs1.head + new HashMap1(kv._1,hash,kv._2,kv) + case x if x == kvs.size => + this + case _ => + new HashMapCollision1(hash, kvs1) + } } else this + override protected def filter0(p: ((A, B)) => Boolean, negate: Boolean, level: Int, buffer: Array[HashMap[A, B @uV]], offset0: Int): HashMap[A, B] = { + val kvs1 = if(negate) kvs.filterNot(p) else kvs.filter(p) + kvs1.size match { + case 0 => + null + case 1 => + val kv@(k,v) = kvs1.head + new HashMap1(k, hash, v, kv) + case x if x == kvs.size => + this + case _ => + new HashMapCollision1(hash, kvs1) + } + } + override def iterator: Iterator[(A,B)] = kvs.iterator override def foreach[U](f: ((A, B)) => U): Unit = kvs.foreach(f) override def split: Seq[HashMap[A, B]] = { @@ -283,24 +299,6 @@ object HashMap extends ImmutableMapFactory[HashMap] with BitOperations.Int { // assert(Integer.bitCount(bitmap) == elems.length) // assert(elems.length > 1 || (elems.length == 1 && elems(0).isInstanceOf[HashTrieMap[_,_]])) -/* - def this (level: Int, m1: HashMap1[A,B], m2: HashMap1[A,B]) = { - this(((m1.hash >>> level) & 0x1f) | ((m2.hash >>> level) & 0x1f), { - val idx1 = (m1.hash >>> level) & 0x1f - val idx2 = (m2.hash >>> level) & 0x1f - assert(idx1 != idx2, m1.hash + "==" + m2.hash + " at level " + level) // TODO - val elems = new Array[HashMap[A,B]](2) - if (idx1 < idx2) { - elems(0) = m1 - elems(1) = m2 - } else { - elems(0) = m2 - elems(1) = m1 - } - elems - }, 2) - } -*/ override def size = size0 override def get0(key: A, hash: Int, level: Int): Option[B] = { @@ -310,7 +308,6 @@ object HashMap extends ImmutableMapFactory[HashMap] with BitOperations.Int { elems(index & 0x1f).get0(key, hash, level + 5) } else if ((bitmap & mask) != 0) { val offset = Integer.bitCount(bitmap & (mask-1)) - // TODO: might be worth checking if sub is HashTrieMap (-> monomorphic call site) elems(offset).get0(key, hash, level + 5) } else None @@ -322,7 +319,6 @@ object HashMap extends ImmutableMapFactory[HashMap] with BitOperations.Int { val offset = Integer.bitCount(bitmap & (mask-1)) if ((bitmap & mask) != 0) { val sub = elems(offset) - // TODO: might be worth checking if sub is HashTrieMap (-> monomorphic call site) val subNew = sub.updated0(key, hash, level + 5, value, kv, merger) if(subNew eq sub) this else { val elemsNew = new Array[HashMap[A,B1]](elems.length) @@ -345,7 +341,6 @@ object HashMap extends ImmutableMapFactory[HashMap] with BitOperations.Int { val offset = Integer.bitCount(bitmap & (mask-1)) if ((bitmap & mask) != 0) { val sub = elems(offset) - // TODO: might be worth checking if sub is HashTrieMap (-> monomorphic call site) val subNew = sub.removed0(key, hash, level + 5) if (subNew eq sub) this else if (subNew.isEmpty) { @@ -355,6 +350,8 @@ object HashMap extends ImmutableMapFactory[HashMap] with BitOperations.Int { Array.copy(elems, 0, elemsNew, 0, offset) Array.copy(elems, offset + 1, elemsNew, offset, elems.length - offset - 1) val sizeNew = size - sub.size + // if we have only one child, which is not a HashTrieSet but a self-contained set like + // HashSet1 or HashSetCollision1, return the child instead if (elemsNew.length == 1 && !elemsNew(0).isInstanceOf[HashTrieMap[_,_]]) elemsNew(0) else @@ -375,30 +372,58 @@ object HashMap extends ImmutableMapFactory[HashMap] with BitOperations.Int { } } + override protected def filter0(p: ((A, B)) => Boolean, negate: Boolean, level: Int, buffer: Array[HashMap[A, B @uV]], offset0: Int): HashMap[A, B] = { + // current offset + var offset = offset0 + // result size + var rs = 0 + // bitmap for kept elems + var kept = 0 + // loop over all elements + var i = 0 + while (i < elems.length) { + val result = elems(i).filter0(p, negate, level + 5, buffer, offset) + if (result ne null) { + buffer(offset) = result + offset += 1 + // add the result size + rs += result.size + // mark the bit i as kept + kept |= (1 << i) + } + i += 1 + } + if (offset == offset0) { + // empty + null + } else if (rs == size0) { + // unchanged + this + } else if (offset == offset0 + 1 && !buffer(offset0).isInstanceOf[HashTrieMap[A, B]]) { + // leaf + buffer(offset0) + } else { + // we have to return a HashTrieMap + val length = offset - offset0 + val elems1 = new Array[HashMap[A, B]](length) + System.arraycopy(buffer, offset0, elems1, 0, length) + val bitmap1 = if (length == elems.length) { + // we can reuse the original bitmap + bitmap + } else { + // calculate new bitmap by keeping just bits in the kept bitmask + keepBits(bitmap, kept) + } + new HashTrieMap(bitmap1, elems1, rs) + } + } + override def iterator: Iterator[(A, B)] = new TrieIterator[(A, B)](elems.asInstanceOf[Array[Iterable[(A, B)]]]) { final override def getElem(cc: AnyRef): (A, B) = cc.asInstanceOf[HashMap1[A, B]].ensurePair } -/* -def time(block: =>Unit) = { val t0 = System.nanoTime; block; println("elapsed: " + (System.nanoTime - t0)/1000000.0) } -var mOld = OldHashMap.empty[Int,Int] -var mNew = HashMap.empty[Int,Int] -time { for (i <- 0 until 100000) mOld = mOld.updated(i,i) } -time { for (i <- 0 until 100000) mOld = mOld.updated(i,i) } -time { for (i <- 0 until 100000) mOld = mOld.updated(i,i) } -time { for (i <- 0 until 100000) mNew = mNew.updated(i,i) } -time { for (i <- 0 until 100000) mNew = mNew.updated(i,i) } -time { for (i <- 0 until 100000) mNew = mNew.updated(i,i) } -time { mOld.iterator.foreach( p => ()) } -time { mOld.iterator.foreach( p => ()) } -time { mOld.iterator.foreach( p => ()) } -time { mNew.iterator.foreach( p => ()) } -time { mNew.iterator.foreach( p => ()) } -time { mNew.iterator.foreach( p => ()) } -*/ - override def foreach[U](f: ((A, B)) => U): Unit = { - var i = 0; + var i = 0 while (i < elems.length) { elems(i).foreach(f) i += 1 @@ -471,9 +496,6 @@ time { mNew.iterator.foreach( p => ()) } // condition below is due to 2 things: // 1) no unsigned int compare on JVM // 2) 0 (no lsb) should always be greater in comparison - val a = thislsb - 1 - val b = thatlsb - 1 - if (unsignedCompare(thislsb - 1, thatlsb - 1)) { val m = thiselems(thisi) totalelems += m.size @@ -499,6 +521,50 @@ time { mNew.iterator.foreach( p => ()) } } } + /** + * Calculates the maximum buffer size given the maximum possible total size of the trie-based collection + * @param size the maximum size of the collection to be generated + * @return the maximum buffer size + */ + @inline private def bufferSize(size: Int): Int = (size + 6) min (32 * 7) + + /** + * In many internal operations the empty map is represented as null for performance reasons. This method converts + * null to the empty map for use in public methods + */ + @inline private def nullToEmpty[A, B](m: HashMap[A, B]): HashMap[A, B] = if (m eq null) empty[A, B] else m + + /** + * Utility method to keep a subset of all bits in a given bitmap + * + * Example + * bitmap (binary): 00000001000000010000000100000001 + * keep (binary): 1010 + * result (binary): 00000001000000000000000100000000 + * + * @param bitmap the bitmap + * @param keep a bitmask containing which bits to keep + * @return the original bitmap with all bits where keep is not 1 set to 0 + */ + private def keepBits(bitmap: Int, keep: Int): Int = { + var result = 0 + var current = bitmap + var kept = keep + while (kept != 0) { + // lowest remaining bit in current + val lsb = current ^ (current & (current - 1)) + if ((kept & 1) != 0) { + // mark bit in result bitmap + result |= lsb + } + // clear lowest remaining one bit in abm + current &= ~lsb + // look at the next kept bit + kept >>>= 1 + } + result + } + @SerialVersionUID(2L) private class SerializationProxy[A,B](@transient private var orig: HashMap[A, B]) extends Serializable { private def writeObject(out: java.io.ObjectOutputStream) { diff --git a/src/library/scala/collection/immutable/HashSet.scala b/src/library/scala/collection/immutable/HashSet.scala index 87995f705f..e4b7371ed4 100644 --- a/src/library/scala/collection/immutable/HashSet.scala +++ b/src/library/scala/collection/immutable/HashSet.scala @@ -12,9 +12,10 @@ package scala package collection package immutable -import scala.annotation.unchecked.{ uncheckedVariance => uV } import generic._ import scala.collection.parallel.immutable.ParHashSet +import scala.collection.GenSet +import scala.annotation.tailrec /** This class implements immutable sets using a hash trie. * @@ -30,6 +31,7 @@ import scala.collection.parallel.immutable.ParHashSet * @define coll immutable hash set */ @SerialVersionUID(2L) +@deprecatedInheritance("The implementation details of immutable hash sets make inheriting from them unwise.", "2.11.0") class HashSet[A] extends AbstractSet[A] with Set[A] with GenericSetTemplate[A, HashSet] @@ -37,6 +39,8 @@ class HashSet[A] extends AbstractSet[A] with CustomParallelizable[A, ParHashSet[A]] with Serializable { + import HashSet.{nullToEmpty, bufferSize, LeafHashSet} + override def companion: GenericCompanion[HashSet] = HashSet //class HashSet[A] extends Set[A] with SetLike[A, HashSet[A]] { @@ -53,14 +57,129 @@ class HashSet[A] extends AbstractSet[A] def contains(e: A): Boolean = get0(e, computeHash(e), 0) + override def subsetOf(that: GenSet[A]) = that match { + case that:HashSet[A] => + // call the specialized implementation with a level of 0 since both this and that are top-level hash sets + subsetOf0(that, 0) + case _ => + // call the generic implementation + super.subsetOf(that) + } + + /** + * A specialized implementation of subsetOf for when both this and that are HashSet[A] and we can take advantage + * of the tree structure of both operands and the precalculated hashcodes of the HashSet1 instances. + * @param that the other set + * @param level the level of this and that hashset + * The purpose of level is to keep track of how deep we are in the tree. + * We need this information for when we arrive at a leaf and have to call get0 on that + * The value of level is 0 for a top-level HashSet and grows in increments of 5 + * @return true if all elements of this set are contained in that set + */ + protected def subsetOf0(that: HashSet[A], level: Int) = { + // The default implementation is for the empty set and returns true because the empty set is a subset of all sets + true + } + override def + (e: A): HashSet[A] = updated0(e, computeHash(e), 0) override def + (elem1: A, elem2: A, elems: A*): HashSet[A] = this + elem1 + elem2 ++ elems - // TODO: optimize (might be able to use mutable updates) + + override def union(that: GenSet[A]): HashSet[A] = that match { + case that: HashSet[A] => + val buffer = new Array[HashSet[A]](bufferSize(this.size + that.size)) + nullToEmpty(union0(that, 0, buffer, 0)) + case _ => super.union(that) + } + + override def intersect(that: GenSet[A]): HashSet[A] = that match { + case that: HashSet[A] => + val buffer = new Array[HashSet[A]](bufferSize(this.size min that.size)) + nullToEmpty(intersect0(that, 0, buffer, 0)) + case _ => super.intersect(that) + } + + override def diff(that: GenSet[A]): HashSet[A] = that match { + case that: HashSet[A] => + val buffer = new Array[HashSet[A]](bufferSize(this.size)) + nullToEmpty(diff0(that, 0, buffer, 0)) + case _ => super.diff(that) + } + + /** + * Union with a leaf HashSet at a given level. + * @param that a leaf HashSet + * @param level the depth in the tree. We need this when we have to create a branch node on top of this and that + * @return The union of this and that at the given level. Unless level is zero, the result is not a self-contained + * HashSet but needs to be stored at the correct depth + */ + private[immutable] def union0(that: LeafHashSet[A], level: Int): HashSet[A] = { + // the default implementation is for the empty set, so we just return that + that + } + + /** + * Union with a HashSet at a given level + * @param that a HashSet + * @param level the depth in the tree. We need to keep track of the level to know how deep we are in the tree + * @param buffer a temporary buffer that is used for temporarily storing elements when creating new branch nodes + * @param offset0 the first offset into the buffer in which we are allowed to write + * @return The union of this and that at the given level. Unless level is zero, the result is not a self-contained + * HashSet but needs to be stored at the correct depth + */ + private[immutable] def union0(that: HashSet[A], level: Int, buffer: Array[HashSet[A]], offset0: Int): HashSet[A] = { + // the default implementation is for the empty set, so we just return that + that + } + + /** + * Intersection with another hash set at a given level + * @param level the depth in the tree. We need to keep track of the level to know how deep we are in the tree + * @param buffer a temporary buffer that is used for temporarily storing elements when creating new branch nodes + * @param offset0 the first offset into the buffer in which we are allowed to write + * @return The intersection of this and that at the given level. Unless level is zero, the result is not a + * self-contained HashSet but needs to be stored at the correct depth + */ + private[immutable] def intersect0(that: HashSet[A], level: Int, buffer: Array[HashSet[A]], offset0: Int): HashSet[A] = { + // the default implementation is for the empty set, so we just return the empty set + null + } + + /** + * Diff with another hash set at a given level + * @param level the depth in the tree. We need to keep track of the level to know how deep we are in the tree + * @param buffer a temporary buffer that is used for temporarily storing elements when creating new branch nodes + * @param offset0 the first offset into the buffer in which we are allowed to write + * @return The diff of this and that at the given level. Unless level is zero, the result is not a + * self-contained HashSet but needs to be stored at the correct depth + */ + private[immutable] def diff0(that: HashSet[A], level: Int, buffer: Array[HashSet[A]], offset0: Int): HashSet[A] = { + // the default implementation is for the empty set, so we just return the empty set + null + } def - (e: A): HashSet[A] = - removed0(e, computeHash(e), 0) + nullToEmpty(removed0(e, computeHash(e), 0)) + + /** Returns this $coll as an immutable set. + * + * A new set will not be built; lazy collections will stay lazy. + */ + @deprecatedOverriding("Immutable sets should do nothing on toSet but return themselves cast as a Set.", "2.11.0") + override def toSet[B >: A]: Set[B] = this.asInstanceOf[Set[B]] + + override def filter(p: A => Boolean) = { + val buffer = new Array[HashSet[A]](bufferSize(size)) + nullToEmpty(filter0(p, false, 0, buffer, 0)) + } + + override def filterNot(p: A => Boolean) = { + val buffer = new Array[HashSet[A]](bufferSize(size)) + nullToEmpty(filter0(p, true, 0, buffer, 0)) + } + + protected def filter0(p: A => Boolean, negate: Boolean, level: Int, buffer: Array[HashSet[A]], offset0: Int): HashSet[A] = null protected def elemHashCode(key: A) = key.## @@ -99,10 +218,10 @@ object HashSet extends ImmutableSetFactory[HashSet] { /** $setCanBuildFromInfo */ implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, HashSet[A]] = setCanBuildFrom[A] - override def empty[A]: HashSet[A] = EmptyHashSet.asInstanceOf[HashSet[A]] private object EmptyHashSet extends HashSet[Any] { } - + private[collection] def emptyInstance: HashSet[Any] = EmptyHashSet + // utility method to create a HashTrieSet from two leaf HashSets (HashSet1 or HashSetCollision1) with non-colliding hash code) private def makeHashTrieSet[A](hash0:Int, elem0:HashSet[A], hash1:Int, elem1:HashSet[A], level:Int) : HashTrieSet[A] = { val index0 = (hash0 >>> level) & 0x1f @@ -127,14 +246,27 @@ object HashSet extends ImmutableSetFactory[HashSet] { } } - // TODO: add HashSet2, HashSet3, ... + /** + * Common superclass of HashSet1 and HashSetCollision1, which are the two possible leaves of the Trie + */ + private[HashSet] sealed abstract class LeafHashSet[A] extends HashSet[A] { + private[HashSet] def hash:Int + } - class HashSet1[A](private[HashSet] val key: A, private[HashSet] val hash: Int) extends HashSet[A] { + class HashSet1[A](private[HashSet] val key: A, private[HashSet] val hash: Int) extends LeafHashSet[A] { override def size = 1 override def get0(key: A, hash: Int, level: Int): Boolean = (hash == this.hash && key == this.key) + override def subsetOf0(that: HashSet[A], level: Int) = { + // check if that contains this.key + // we use get0 with our key and hash at the correct level instead of calling contains, + // which would not work since that might not be a top-level HashSet + // and in any case would be inefficient because it would require recalculating the hash code + that.get0(key, hash, level) + } + override def updated0(key: A, hash: Int, level: Int): HashSet[A] = if (hash == this.hash && key == this.key) this else { @@ -146,35 +278,191 @@ object HashSet extends ImmutableSetFactory[HashSet] { } } + override private[immutable] def union0(that: LeafHashSet[A], level: Int): HashSet[A] = that match { + case that if that.hash != this.hash => + // different hash code, so there is no need to investigate further. + // Just create a branch node containing the two. + makeHashTrieSet(this.hash, this, that.hash, that, level) + case that: HashSet1[A] => + if (this.key == that.key) { + this + } else { + // 32-bit hash collision (rare, but not impossible) + new HashSetCollision1[A](hash, ListSet.empty + this.key + that.key) + } + case that: HashSetCollision1[A] => + val ks1 = that.ks + key + // Could use eq check (faster) if ListSet was guaranteed to return itself + if (ks1.size == that.ks.size) { + that + } else { + new HashSetCollision1[A](hash, ks1) + } + } + + override private[immutable] def union0(that: HashSet[A], level: Int, buffer: Array[HashSet[A]], offset0: Int) = { + // switch to the Leaf version of union + // we can exchange the arguments because union is symmetrical + that.union0(this, level) + } + + override private[immutable] def intersect0(that: HashSet[A], level: Int, buffer: Array[HashSet[A]], offset0: Int): HashSet[A] = + if (that.get0(key, hash, level)) this else null + + override private[immutable] def diff0(that: HashSet[A], level: Int, buffer: Array[HashSet[A]], offset0: Int): HashSet[A] = + if (that.get0(key, hash, level)) null else this + override def removed0(key: A, hash: Int, level: Int): HashSet[A] = - if (hash == this.hash && key == this.key) HashSet.empty[A] else this + if (hash == this.hash && key == this.key) null else this + + override protected def filter0(p: A => Boolean, negate: Boolean, level: Int, buffer: Array[HashSet[A]], offset0: Int): HashSet[A] = + if (negate ^ p(key)) this else null override def iterator: Iterator[A] = Iterator(key) override def foreach[U](f: A => U): Unit = f(key) } - private[immutable] class HashSetCollision1[A](private[HashSet] val hash: Int, val ks: ListSet[A]) - extends HashSet[A] { + private[immutable] class HashSetCollision1[A](private[HashSet] val hash: Int, val ks: ListSet[A]) extends LeafHashSet[A] { override def size = ks.size override def get0(key: A, hash: Int, level: Int): Boolean = if (hash == this.hash) ks.contains(key) else false + override def subsetOf0(that: HashSet[A], level: Int) = { + // we have to check each element + // we use get0 with our hash at the correct level instead of calling contains, + // which would not work since that might not be a top-level HashSet + // and in any case would be inefficient because it would require recalculating the hash code + ks.forall(key => that.get0(key, hash, level)) + } + override def updated0(key: A, hash: Int, level: Int): HashSet[A] = if (hash == this.hash) new HashSetCollision1(hash, ks + key) else makeHashTrieSet(this.hash, this, hash, new HashSet1(key, hash), level) + override def union0(that: LeafHashSet[A], level: Int): HashSet[A] = that match { + case that if that.hash != this.hash => + // different hash code, so there is no need to investigate further. + // Just create a branch node containing the two. + makeHashTrieSet(this.hash, this, that.hash, that, level) + case that: HashSet1[A] => + val ks1 = ks + that.key + // Could use eq check (faster) if ListSet was guaranteed to return itself + if (ks1.size == ks.size) { + this + } else { + // create a new HashSetCollision with the existing hash + // we don't have to check for size=1 because union is never going to remove elements + new HashSetCollision1[A](hash, ks1) + } + case that: HashSetCollision1[A] => + val ks1 = this.ks ++ that.ks + ks1.size match { + case size if size == this.ks.size => + // could this check be made faster by doing an eq check? + // I am not sure we can rely on ListSet returning itself when all elements are already in the set, + // so it seems unwise to rely on it. + this + case size if size == that.ks.size => + // we have to check this as well, since we don't want to create a new instance if this is a subset of that + that + case _ => + // create a new HashSetCollision with the existing hash + // we don't have to check for size=1 because union is never going to remove elements + new HashSetCollision1[A](hash, ks1) + } + } + + override def union0(that: HashSet[A], level: Int, buffer: Array[HashSet[A]], offset0: Int): HashSet[A] = that match { + case that: LeafHashSet[A] => + // switch to the simpler Tree/Leaf implementation + this.union0(that, level) + case that: HashTrieSet[A] => + // switch to the simpler Tree/Leaf implementation + // we can swap this and that because union is symmetrical + that.union0(this, level) + case _ => this + } + + override private[immutable] def intersect0(that: HashSet[A], level: Int, buffer: Array[HashSet[A]], offset0: Int): HashSet[A] = { + // filter the keys, taking advantage of the fact that we know their hash code + val ks1 = ks.filter(that.get0(_, hash, level)) + ks1.size match { + case 0 => + // the empty set + null + case size if size == this.size => + // unchanged + // We do this check first since even if the result is of size 1 since + // it is preferable to return the existing set for better structural sharing + this + case size if size == that.size => + // the other set + // We do this check first since even if the result is of size 1 since + // it is preferable to return the existing set for better structural sharing + that + case 1 => + // create a new HashSet1 with the hash we already know + new HashSet1(ks1.head, hash) + case _ => + // create a new HashSetCollison with the hash we already know and the new keys + new HashSetCollision1(hash, ks1) + } + } + + override private[immutable] def diff0(that: HashSet[A], level: Int, buffer: Array[HashSet[A]], offset0: Int): HashSet[A] = { + val ks1 = ks.filterNot(that.get0(_, hash, level)) + ks1.size match { + case 0 => + // the empty set + null + case size if size == this.size => + // unchanged + // We do this check first since even if the result is of size 1 since + // it is preferable to return the existing set for better structural sharing + this + case 1 => + // create a new HashSet1 with the hash we already know + new HashSet1(ks1.head, hash) + case _ => + // create a new HashSetCollison with the hash we already know and the new keys + new HashSetCollision1(hash, ks1) + } + } + override def removed0(key: A, hash: Int, level: Int): HashSet[A] = if (hash == this.hash) { val ks1 = ks - key - if(ks1.isEmpty) - HashSet.empty[A] - else if(ks1.tail.isEmpty) + ks1.size match { + case 0 => + // the empty set + null + case 1 => + // create a new HashSet1 with the hash we already know + new HashSet1(ks1.head, hash) + case size if size == ks.size => + // Should only have HSC1 if size > 1 + this + case _ => + // create a new HashSetCollison with the hash we already know and the new keys + new HashSetCollision1(hash, ks1) + } + } else this + + override protected def filter0(p: A => Boolean, negate: Boolean, level: Int, buffer: Array[HashSet[A]], offset0: Int): HashSet[A] = { + val ks1 = if(negate) ks.filterNot(p) else ks.filter(p) + ks1.size match { + case 0 => + null + case 1 => new HashSet1(ks1.head, hash) - else + case x if x == ks.size => + this + case _ => new HashSetCollision1(hash, ks1) - } else this + } + } override def iterator: Iterator[A] = ks.iterator override def foreach[U](f: A => U): Unit = ks.foreach(f) @@ -196,6 +484,42 @@ object HashSet extends ImmutableSetFactory[HashSet] { } + /** + * A branch node of the HashTrieSet with at least one and up to 32 children. + * + * @param bitmap encodes which element corresponds to which child + * @param elems the up to 32 children of this node. + * the number of children must be identical to the number of 1 bits in bitmap + * @param size0 the total number of elements. This is stored just for performance reasons. + * @tparam A the type of the elements contained in this hash set. + * + * How levels work: + * + * When looking up or adding elements, the part of the hashcode that is used to address the children array depends + * on how deep we are in the tree. This is accomplished by having a level parameter in all internal methods + * that starts at 0 and increases by 5 (32 = 2^5) every time we go deeper into the tree. + * + * hashcode (binary): 00000000000000000000000000000000 + * level=0 (depth=0) ^^^^^ + * level=5 (depth=1) ^^^^^ + * level=10 (depth=2) ^^^^^ + * ... + * + * Be careful: a non-toplevel HashTrieSet is not a self-contained set, so e.g. calling contains on it will not work! + * It relies on its depth in the Trie for which part of a hash to use to address the children, but this information + * (the level) is not stored due to storage efficiency reasons but has to be passed explicitly! + * + * How bitmap and elems correspond: + * + * A naive implementation of a HashTrieSet would always have an array of size 32 for children and leave the unused + * children empty (null). But that would be very wasteful regarding memory. Instead, only non-empty children are + * stored in elems, and the bitmap is used to encode which elem corresponds to which child bucket. The lowest 1 bit + * corresponds to the first element, the second-lowest to the second, etc. + * + * bitmap (binary): 00010000000000000000100000000000 + * elems: [a,b] + * children: ---b----------------a----------- + */ class HashTrieSet[A](private val bitmap: Int, private[collection] val elems: Array[HashSet[A]], private val size0: Int) extends HashSet[A] { assert(Integer.bitCount(bitmap) == elems.length) @@ -211,7 +535,6 @@ object HashSet extends ImmutableSetFactory[HashSet] { elems(index & 0x1f).get0(key, hash, level + 5) } else if ((bitmap & mask) != 0) { val offset = Integer.bitCount(bitmap & (mask-1)) - // TODO: might be worth checking if sub is HashTrieSet (-> monomorphic call site) elems(offset).get0(key, hash, level + 5) } else false @@ -222,7 +545,6 @@ object HashSet extends ImmutableSetFactory[HashSet] { val mask = (1 << index) val offset = Integer.bitCount(bitmap & (mask-1)) if ((bitmap & mask) != 0) { - // TODO: might be worth checking if sub is HashTrieSet (-> monomorphic call site) val sub = elems(offset) val subNew = sub.updated0(key, hash, level + 5) if (sub eq subNew) this @@ -242,16 +564,293 @@ object HashSet extends ImmutableSetFactory[HashSet] { } } + override private[immutable] def union0(that: LeafHashSet[A], level: Int): HashSet[A] = { + val index = (that.hash >>> level) & 0x1f + val mask = (1 << index) + val offset = Integer.bitCount(bitmap & (mask - 1)) + if ((bitmap & mask) != 0) { + val sub = elems(offset) + val sub1 = sub.union0(that, level + 5) + if (sub eq sub1) this + else { + val elems1 = new Array[HashSet[A]](elems.length) + Array.copy(elems, 0, elems1, 0, elems.length) + elems1(offset) = sub1 + new HashTrieSet(bitmap, elems1, size + (sub1.size - sub.size)) + } + } else { + val elems1 = new Array[HashSet[A]](elems.length + 1) + Array.copy(elems, 0, elems1, 0, offset) + elems1(offset) = that + Array.copy(elems, offset, elems1, offset + 1, elems.length - offset) + val bitmap1 = bitmap | mask + new HashTrieSet(bitmap1, elems1, size + that.size) + } + } + + override private[immutable] def union0(that: HashSet[A], level: Int, buffer: Array[HashSet[A]], offset0: Int): HashSet[A] = that match { + case that if that eq this => + // shortcut for when that is this + // this happens often for nodes deeper in the tree, especially when that and this share a common "heritage" + // e.g. you have a large set A and do some small operations (adding and removing elements) to it to create B + // then A and B will have the vast majority of nodes in common, and this eq check will allow not even looking + // at these nodes. + this + case that: LeafHashSet[A] => + // when that is a leaf, we can switch to the simpler Tree/Leaf implementation + this.union0(that, level) + case that: HashTrieSet[A] => + val a = this.elems + var abm = this.bitmap + var ai = 0 + + val b = that.elems + var bbm = that.bitmap + var bi = 0 + + // fetch a new temporary array that is guaranteed to be big enough (32 elements) + var offset = offset0 + var rs = 0 + + // loop as long as there are bits left in either abm or bbm + while ((abm | bbm) != 0) { + // lowest remaining bit in abm + val alsb = abm ^ (abm & (abm - 1)) + // lowest remaining bit in bbm + val blsb = bbm ^ (bbm & (bbm - 1)) + if (alsb == blsb) { + val sub1 = a(ai).union0(b(bi), level + 5, buffer, offset) + rs += sub1.size + buffer(offset) = sub1 + offset += 1 + // clear lowest remaining one bit in abm and increase the a index + abm &= ~alsb + ai += 1 + // clear lowest remaining one bit in bbm and increase the b index + bbm &= ~blsb + bi += 1 + } else if (unsignedCompare(alsb - 1, blsb - 1)) { + // alsb is smaller than blsb, or alsb is set and blsb is 0 + // in any case, alsb is guaranteed to be set here! + val sub1 = a(ai) + rs += sub1.size + buffer(offset) = sub1 + offset += 1 + // clear lowest remaining one bit in abm and increase the a index + abm &= ~alsb + ai += 1 + } else { + // blsb is smaller than alsb, or blsb is set and alsb is 0 + // in any case, blsb is guaranteed to be set here! + val sub1 = b(bi) + rs += sub1.size + buffer(offset) = sub1 + offset += 1 + // clear lowest remaining one bit in bbm and increase the b index + bbm &= ~blsb + bi += 1 + } + } + if (rs == this.size) { + // if the result would be identical to this, we might as well return this + this + } else if (rs == that.size) { + // if the result would be identical to that, we might as well return that + that + } else { + // we don't have to check whether the result is a leaf, since union will only make the set larger + // and this is not a leaf to begin with. + val length = offset - offset0 + val elems = new Array[HashSet[A]](length) + System.arraycopy(buffer, offset0, elems, 0, length) + new HashTrieSet(this.bitmap | that.bitmap, elems, rs) + } + case _ => this + } + + override private[immutable] def intersect0(that: HashSet[A], level: Int, buffer: Array[HashSet[A]], offset0: Int): HashSet[A] = that match { + case that if that eq this => + // shortcut for when that is this + // this happens often for nodes deeper in the tree, especially when that and this share a common "heritage" + // e.g. you have a large set A and do some small operations (adding and removing elements) to it to create B + // then A and B will have the vast majority of nodes in common, and this eq check will allow not even looking + // at these nodes! + this + case that: LeafHashSet[A] => + // when that is a leaf, we can switch to the simpler Tree/Leaf implementation + // it is OK to swap the arguments because intersect is symmetric + // (we can't do this in case of diff, which is not symmetric) + that.intersect0(this, level, buffer, offset0) + case that: HashTrieSet[A] => + val a = this.elems + var abm = this.bitmap + var ai = 0 + + val b = that.elems + var bbm = that.bitmap + var bi = 0 + + // if the bitmasks do not overlap, the result is definitely empty so we can abort here + if ((abm & bbm) == 0) + return null + + // fetch a new temporary array that is guaranteed to be big enough (32 elements) + var offset = offset0 + var rs = 0 + var rbm = 0 + + // loop as long as there are bits left that are set in both abm and bbm + while ((abm & bbm) != 0) { + // highest remaining bit in abm + val alsb = abm ^ (abm & (abm - 1)) + // highest remaining bit in bbm + val blsb = bbm ^ (bbm & (bbm - 1)) + if (alsb == blsb) { + val sub1 = a(ai).intersect0(b(bi), level + 5, buffer, offset) + if (sub1 ne null) { + rs += sub1.size + rbm |= alsb + buffer(offset) = sub1 + offset += 1 + } + // clear lowest remaining one bit in abm and increase the a index + abm &= ~alsb; + ai += 1 + // clear lowest remaining one bit in bbm and increase the b index + bbm &= ~blsb; + bi += 1 + } else if (unsignedCompare(alsb - 1, blsb - 1)) { + // alsb is smaller than blsb, or alsb is set and blsb is 0 + // in any case, alsb is guaranteed to be set here! + // clear lowest remaining one bit in abm and increase the a index + abm &= ~alsb; + ai += 1 + } else { + // blsb is smaller than alsb, or blsb is set and alsb is 0 + // in any case, blsb is guaranteed to be set here! + // clear lowest remaining one bit in bbm and increase the b index + bbm &= ~blsb; + bi += 1 + } + } + + if (rbm == 0) { + // if the result bitmap is empty, the result is the empty set + null + } else if (rs == size0) { + // if the result has the same number of elements as this, it must be identical to this, + // so we might as well return this + this + } else if (rs == that.size0) { + // if the result has the same number of elements as that, it must be identical to that, + // so we might as well return that + that + } else { + val length = offset - offset0 + if (length == 1 && !buffer(offset0).isInstanceOf[HashTrieSet[A]]) + buffer(offset0) + else { + val elems = new Array[HashSet[A]](length) + System.arraycopy(buffer, offset0, elems, 0, length) + new HashTrieSet[A](rbm, elems, rs) + } + } + case _ => null + } + + override private[immutable] def diff0(that: HashSet[A], level: Int, buffer: Array[HashSet[A]], offset0: Int): HashSet[A] = that match { + case that if that eq this => + // shortcut for when that is this + // this happens often for nodes deeper in the tree, especially when that and this share a common "heritage" + // e.g. you have a large set A and do some small operations (adding and removing elements) to it to create B + // then A and B will have the vast majority of nodes in common, and this eq check will allow not even looking + // at these nodes! + null + case that: HashSet1[A] => + removed0(that.key, that.hash, level) + case that: HashTrieSet[A] => + val a = this.elems + var abm = this.bitmap + var ai = 0 + + val b = that.elems + var bbm = that.bitmap + var bi = 0 + + // fetch a new temporary array that is guaranteed to be big enough (32 elements) + var offset = offset0 + var rs = 0 + var rbm = 0 + + // loop until there are no more bits in abm + while(abm!=0) { + // highest remaining bit in abm + val alsb = abm ^ (abm & (abm - 1)) + // highest remaining bit in bbm + val blsb = bbm ^ (bbm & (bbm - 1)) + if (alsb == blsb) { + val sub1 = a(ai).diff0(b(bi), level + 5, buffer, offset) + if (sub1 ne null) { + rs += sub1.size + rbm |= alsb + buffer(offset) = sub1 + offset += 1 + } + // clear lowest remaining one bit in abm and increase the a index + abm &= ~alsb; ai += 1 + // clear lowest remaining one bit in bbm and increase the b index + bbm &= ~blsb; bi += 1 + } else if (unsignedCompare(alsb - 1, blsb - 1)) { + // alsb is smaller than blsb, or alsb is set and blsb is 0 + // in any case, alsb is guaranteed to be set here! + val sub1 = a(ai) + rs += sub1.size + rbm |= alsb + buffer(offset) = sub1; offset += 1 + // clear lowest remaining one bit in abm and increase the a index + abm &= ~alsb; ai += 1 + } else { + // blsb is smaller than alsb, or blsb is set and alsb is 0 + // in any case, blsb is guaranteed to be set here! + // clear lowest remaining one bit in bbm and increase the b index + bbm &= ~blsb; bi += 1 + } + } + if (rbm == 0) { + null + } else if (rs == this.size0) { + // if the result has the same number of elements as this, it must be identical to this, + // so we might as well return this + this + } else { + val length = offset - offset0 + if (length == 1 && !buffer(offset0).isInstanceOf[HashTrieSet[A]]) + buffer(offset0) + else { + val elems = new Array[HashSet[A]](length) + System.arraycopy(buffer, offset0, elems, 0, length) + new HashTrieSet[A](rbm, elems, rs) + } + } + case that: HashSetCollision1[A] => + // we remove the elements using removed0 so we can use the fact that we know the hash of all elements + // to be removed + @tailrec def removeAll(s:HashSet[A], r:ListSet[A]) : HashSet[A] = + if(r.isEmpty || (s eq null)) s + else removeAll(s.removed0(r.head, that.hash, level), r.tail) + removeAll(this, that.ks) + case _ => this + } + override def removed0(key: A, hash: Int, level: Int): HashSet[A] = { val index = (hash >>> level) & 0x1f val mask = (1 << index) val offset = Integer.bitCount(bitmap & (mask-1)) if ((bitmap & mask) != 0) { val sub = elems(offset) - // TODO: might be worth checking if sub is HashTrieMap (-> monomorphic call site) val subNew = sub.removed0(key, hash, level + 5) if (sub eq subNew) this - else if (subNew.isEmpty) { + else if (subNew eq null) { val bitmapNew = bitmap ^ mask if (bitmapNew != 0) { val elemsNew = new Array[HashSet[A]](elems.length - 1) @@ -265,7 +864,9 @@ object HashSet extends ImmutableSetFactory[HashSet] { else new HashTrieSet(bitmapNew, elemsNew, sizeNew) } else - HashSet.empty[A] + null + } else if(elems.length == 1 && !subNew.isInstanceOf[HashTrieSet[_]]) { + subNew } else { val elemsNew = new Array[HashSet[A]](elems.length) Array.copy(elems, 0, elemsNew, 0, elems.length) @@ -278,30 +879,101 @@ object HashSet extends ImmutableSetFactory[HashSet] { } } + override def subsetOf0(that: HashSet[A], level: Int): Boolean = if (that eq this) true else that match { + case that: HashTrieSet[A] if this.size0 <= that.size0 => + // create local mutable copies of members + var abm = this.bitmap + val a = this.elems + var ai = 0 + val b = that.elems + var bbm = that.bitmap + var bi = 0 + if ((abm & bbm) == abm) { + // I tried rewriting this using tail recursion, but the generated java byte code was less than optimal + while(abm!=0) { + // highest remaining bit in abm + val alsb = abm ^ (abm & (abm - 1)) + // highest remaining bit in bbm + val blsb = bbm ^ (bbm & (bbm - 1)) + // if both trees have a bit set at the same position, we need to check the subtrees + if (alsb == blsb) { + // we are doing a comparison of a child of this with a child of that, + // so we have to increase the level by 5 to keep track of how deep we are in the tree + if (!a(ai).subsetOf0(b(bi), level + 5)) + return false + // clear lowest remaining one bit in abm and increase the a index + abm &= ~alsb; ai += 1 + } + // clear lowermost remaining one bit in bbm and increase the b index + // we must do this in any case + bbm &= ~blsb; bi += 1 + } + true + } else { + // the bitmap of this contains more one bits than the bitmap of that, + // so this can not possibly be a subset of that + false + } + case _ => + // if the other set is a HashTrieSet but has less elements than this, it can not be a subset + // if the other set is a HashSet1, we can not be a subset of it because we are a HashTrieSet with at least two children (see assertion) + // if the other set is a HashSetCollision1, we can not be a subset of it because we are a HashTrieSet with at least two different hash codes + // if the other set is the empty set, we are not a subset of it because we are not empty + false + } + + override protected def filter0(p: A => Boolean, negate: Boolean, level: Int, buffer: Array[HashSet[A]], offset0: Int): HashSet[A] = { + // current offset + var offset = offset0 + // result size + var rs = 0 + // bitmap for kept elems + var kept = 0 + // loop over all elements + var i = 0 + while (i < elems.length) { + val result = elems(i).filter0(p, negate, level + 5, buffer, offset) + if (result ne null) { + buffer(offset) = result + offset += 1 + // add the result size + rs += result.size + // mark the bit i as kept + kept |= (1 << i) + } + i += 1 + } + if (offset == offset0) { + // empty + null + } else if (rs == size0) { + // unchanged + this + } else if (offset == offset0 + 1 && !buffer(offset0).isInstanceOf[HashTrieSet[A]]) { + // leaf + buffer(offset0) + } else { + // we have to return a HashTrieSet + val length = offset - offset0 + val elems1 = new Array[HashSet[A]](length) + System.arraycopy(buffer, offset0, elems1, 0, length) + val bitmap1 = if (length == elems.length) { + // we can reuse the original bitmap + bitmap + } else { + // calculate new bitmap by keeping just bits in the kept bitmask + keepBits(bitmap, kept) + } + new HashTrieSet(bitmap1, elems1, rs) + } + } + override def iterator = new TrieIterator[A](elems.asInstanceOf[Array[Iterable[A]]]) { final override def getElem(cc: AnyRef): A = cc.asInstanceOf[HashSet1[A]].key } -/* - -def time(block: =>Unit) = { val t0 = System.nanoTime; block; println("elapsed: " + (System.nanoTime - t0)/1000000.0) } -var mOld = OldHashSet.empty[Int] -var mNew = HashSet.empty[Int] -time { for (i <- 0 until 100000) mOld = mOld + i } -time { for (i <- 0 until 100000) mOld = mOld + i } -time { for (i <- 0 until 100000) mOld = mOld + i } -time { for (i <- 0 until 100000) mNew = mNew + i } -time { for (i <- 0 until 100000) mNew = mNew + i } -time { for (i <- 0 until 100000) mNew = mNew + i } -time { mOld.iterator.foreach( p => ()) } -time { mOld.iterator.foreach( p => ()) } -time { mOld.iterator.foreach( p => ()) } -time { mNew.iterator.foreach( p => ()) } -time { mNew.iterator.foreach( p => ()) } -time { mNew.iterator.foreach( p => ()) } - -*/ + override def foreach[U](f: A => U): Unit = { - var i = 0; + var i = 0 while (i < elems.length) { elems(i).foreach(f) i += 1 @@ -309,6 +981,54 @@ time { mNew.iterator.foreach( p => ()) } } } + /** + * Calculates the maximum buffer size given the maximum possible total size of the trie-based collection + * @param size the maximum size of the collection to be generated + * @return the maximum buffer size + */ + @inline private def bufferSize(size: Int): Int = (size + 6) min (32 * 7) + + /** + * In many internal operations the empty set is represented as null for performance reasons. This method converts + * null to the empty set for use in public methods + */ + @inline private def nullToEmpty[A](s: HashSet[A]): HashSet[A] = if (s eq null) empty[A] else s + + /** + * Utility method to keep a subset of all bits in a given bitmap + * + * Example + * bitmap (binary): 00000001000000010000000100000001 + * keep (binary): 1010 + * result (binary): 00000001000000000000000100000000 + * + * @param bitmap the bitmap + * @param keep a bitmask containing which bits to keep + * @return the original bitmap with all bits where keep is not 1 set to 0 + */ + private def keepBits(bitmap: Int, keep: Int): Int = { + var result = 0 + var current = bitmap + var kept = keep + while (kept != 0) { + // lowest remaining bit in current + val lsb = current ^ (current & (current - 1)) + if ((kept & 1) != 0) { + // mark bit in result bitmap + result |= lsb + } + // clear lowest remaining one bit in abm + current &= ~lsb + // look at the next kept bit + kept >>>= 1 + } + result + } + + // unsigned comparison + @inline private[this] def unsignedCompare(i: Int, j: Int) = + (i < j) ^ (i < 0) ^ (j < 0) + @SerialVersionUID(2L) private class SerializationProxy[A,B](@transient private var orig: HashSet[A]) extends Serializable { private def writeObject(out: java.io.ObjectOutputStream) { val s = orig.size diff --git a/src/library/scala/collection/immutable/IndexedSeq.scala b/src/library/scala/collection/immutable/IndexedSeq.scala index 96414c07ef..06a44b2bf3 100644 --- a/src/library/scala/collection/immutable/IndexedSeq.scala +++ b/src/library/scala/collection/immutable/IndexedSeq.scala @@ -7,7 +7,8 @@ \* */ -package scala.collection +package scala +package collection package immutable import generic._ @@ -22,6 +23,12 @@ trait IndexedSeq[+A] extends Seq[A] with GenericTraversableTemplate[A, IndexedSeq] with IndexedSeqLike[A, IndexedSeq[A]] { override def companion: GenericCompanion[IndexedSeq] = IndexedSeq + + /** Returns this $coll as an indexed sequence. + * + * A new indexed sequence will not be built; lazy collections will stay lazy. + */ + @deprecatedOverriding("Immutable indexed sequences should do nothing on toIndexedSeq except cast themselves as an indexed sequence.", "2.11.0") override def toIndexedSeq: IndexedSeq[A] = this override def seq: IndexedSeq[A] = this } @@ -31,14 +38,13 @@ trait IndexedSeq[+A] extends Seq[A] * @define coll indexed sequence * @define Coll `IndexedSeq` */ -object IndexedSeq extends SeqFactory[IndexedSeq] { - override lazy val ReusableCBF = - scala.collection.IndexedSeq.ReusableCBF.asInstanceOf[GenericCanBuildFrom[Nothing]] +object IndexedSeq extends IndexedSeqFactory[IndexedSeq] { class Impl[A](buf: ArrayBuffer[A]) extends AbstractSeq[A] with IndexedSeq[A] with Serializable { def length = buf.length def apply(idx: Int) = buf.apply(idx) } def newBuilder[A]: Builder[A, IndexedSeq[A]] = Vector.newBuilder[A] + implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, IndexedSeq[A]] = ReusableCBF.asInstanceOf[GenericCanBuildFrom[A]] } diff --git a/src/library/scala/collection/immutable/IntMap.scala b/src/library/scala/collection/immutable/IntMap.scala index ab1faf363e..8991d0b75a 100644 --- a/src/library/scala/collection/immutable/IntMap.scala +++ b/src/library/scala/collection/immutable/IntMap.scala @@ -12,6 +12,7 @@ package immutable import scala.collection.generic.{ CanBuildFrom, BitOperations } import scala.collection.mutable.{ Builder, MapBuilder } +import scala.annotation.tailrec /** Utility class for integer maps. * @author David MacIver @@ -50,8 +51,10 @@ object IntMap { def apply(): Builder[(Int, B), IntMap[B]] = new MapBuilder[Int, B, IntMap[B]](empty[B]) } - def empty[T] : IntMap[T] = IntMap.Nil; - def singleton[T](key: Int, value: T): IntMap[T] = IntMap.Tip(key, value); + def empty[T] : IntMap[T] = IntMap.Nil + + def singleton[T](key: Int, value: T): IntMap[T] = IntMap.Tip(key, value) + def apply[T](elems: (Int, T)*): IntMap[T] = elems.foldLeft(empty[T])((x, y) => x.updated(y._1, y._2)) @@ -210,7 +213,7 @@ sealed abstract class IntMap[+T] extends AbstractMap[Int, T] } /** - * Loop over the keys of the map. The same as `keys.foreach(f)`, but may + * Loop over the values of the map. The same as `values.foreach(f)`, but may * be more efficient. * * @param f The loop body @@ -427,6 +430,7 @@ sealed abstract class IntMap[+T] extends AbstractMap[Int, T] /** * The entry with the lowest key value considered in unsigned order. */ + @tailrec final def firstKey: Int = this match { case Bin(_, _, l, r) => l.firstKey case Tip(k, v) => k @@ -436,6 +440,7 @@ sealed abstract class IntMap[+T] extends AbstractMap[Int, T] /** * The entry with the highest key value considered in unsigned order. */ + @tailrec final def lastKey: Int = this match { case Bin(_, _, l, r) => r.lastKey case Tip(k, v) => k diff --git a/src/library/scala/collection/immutable/Iterable.scala b/src/library/scala/collection/immutable/Iterable.scala index cc64d8ff3c..6e4eb1e45f 100644 --- a/src/library/scala/collection/immutable/Iterable.scala +++ b/src/library/scala/collection/immutable/Iterable.scala @@ -8,7 +8,8 @@ -package scala.collection +package scala +package collection package immutable import generic._ diff --git a/src/library/scala/collection/immutable/LinearSeq.scala b/src/library/scala/collection/immutable/LinearSeq.scala index 5ede6d90d0..2109bd5211 100644 --- a/src/library/scala/collection/immutable/LinearSeq.scala +++ b/src/library/scala/collection/immutable/LinearSeq.scala @@ -8,7 +8,8 @@ -package scala.collection +package scala +package collection package immutable import generic._ diff --git a/src/library/scala/collection/immutable/List.scala b/src/library/scala/collection/immutable/List.scala index 2d6952ff92..930e13a9d3 100644 --- a/src/library/scala/collection/immutable/List.scala +++ b/src/library/scala/collection/immutable/List.scala @@ -6,9 +6,8 @@ ** |/ ** \* */ - - -package scala.collection +package scala +package collection package immutable import generic._ @@ -85,7 +84,8 @@ sealed abstract class List[+A] extends AbstractSeq[A] with LinearSeq[A] with Product with GenericTraversableTemplate[A, List] - with LinearSeqOptimized[A, List[A]] { + with LinearSeqOptimized[A, List[A]] + with Serializable { override def companion: GenericCompanion[List] = List import scala.collection.{Iterable, Traversable, Seq, IndexedSeq} @@ -158,7 +158,9 @@ sealed abstract class List[+A] extends AbstractSeq[A] * @usecase def mapConserve(f: A => A): List[A] * @inheritdoc */ - def mapConserve[B >: A <: AnyRef](f: A => B): List[B] = { + @inline final def mapConserve[B >: A <: AnyRef](f: A => B): List[B] = { + // Note to developers: there exists a duplication between this function and `reflect.internal.util.Collections#map2Conserve`. + // If any successful optimization attempts or other changes are made, please rehash them there too. @tailrec def loop(mapped: ListBuffer[B], unchanged: List[A], pending: List[A]): List[B] = if (pending.isEmpty) { @@ -201,17 +203,19 @@ sealed abstract class List[+A] extends AbstractSeq[A] override def toList: List[A] = this - override def take(n: Int): List[A] = { - val b = new ListBuffer[A] - var i = 0 - var these = this - while (!these.isEmpty && i < n) { + override def take(n: Int): List[A] = if (isEmpty || n <= 0) Nil else { + val h = new ::(head, Nil) + var t = h + var rest = tail + var i = 1 + while ({if (rest.isEmpty) return this; i < n}) { i += 1 - b += these.head - these = these.tail + val nx = new ::(rest.head, Nil) + t.tl = nx + t = nx + rest = rest.tail } - if (these.isEmpty) this - else b.toList + h } override def drop(n: Int): List[A] = { @@ -262,8 +266,87 @@ sealed abstract class List[+A] extends AbstractSeq[A] } (b.toList, these) } + + @noinline // TODO - fix optimizer bug that requires noinline (see SI-8334) + final override def map[B, That](f: A => B)(implicit bf: CanBuildFrom[List[A], B, That]): That = { + if (bf eq List.ReusableCBF) { + if (this eq Nil) Nil.asInstanceOf[That] else { + val h = new ::[B](f(head), Nil) + var t: ::[B] = h + var rest = tail + while (rest ne Nil) { + val nx = new ::(f(rest.head), Nil) + t.tl = nx + t = nx + rest = rest.tail + } + h.asInstanceOf[That] + } + } + else super.map(f) + } + + @noinline // TODO - fix optimizer bug that requires noinline for map; applied here to be safe (see SI-8334) + final override def collect[B, That](pf: PartialFunction[A, B])(implicit bf: CanBuildFrom[List[A], B, That]): That = { + if (bf eq List.ReusableCBF) { + if (this eq Nil) Nil.asInstanceOf[That] else { + var rest = this + var h: ::[B] = null + var x: A = null.asInstanceOf[A] + // Special case for first element + do { + val x: Any = pf.applyOrElse(rest.head, List.partialNotApplied) + if (x.asInstanceOf[AnyRef] ne List.partialNotApplied) h = new ::(x.asInstanceOf[B], Nil) + rest = rest.tail + if (rest eq Nil) return (if (h eq null ) Nil else h).asInstanceOf[That] + } while (h eq null) + var t = h + // Remaining elements + do { + val x: Any = pf.applyOrElse(rest.head, List.partialNotApplied) + if (x.asInstanceOf[AnyRef] ne List.partialNotApplied) { + val nx = new ::(x.asInstanceOf[B], Nil) + t.tl = nx + t = nx + } + rest = rest.tail + } while (rest ne Nil) + h.asInstanceOf[That] + } + } + else super.collect(pf) + } + + @noinline // TODO - fix optimizer bug that requires noinline for map; applied here to be safe (see SI-8334) + final override def flatMap[B, That](f: A => GenTraversableOnce[B])(implicit bf: CanBuildFrom[List[A], B, That]): That = { + if (bf eq List.ReusableCBF) { + if (this eq Nil) Nil.asInstanceOf[That] else { + var rest = this + var found = false + var h: ::[B] = null + var t: ::[B] = null + while (rest ne Nil) { + f(rest.head).foreach{ b => + if (!found) { + h = new ::(b, Nil) + t = h + found = true + } + else { + val nx = new ::(b, Nil) + t.tl = nx + t = nx + } + } + rest = rest.tail + } + (if (!found) Nil else h).asInstanceOf[That] + } + } + else super.flatMap(f) + } - override def takeWhile(p: A => Boolean): List[A] = { + @inline final override def takeWhile(p: A => Boolean): List[A] = { val b = new ListBuffer[A] var these = this while (!these.isEmpty && p(these.head)) { @@ -273,7 +356,7 @@ sealed abstract class List[+A] extends AbstractSeq[A] b.toList } - override def dropWhile(p: A => Boolean): List[A] = { + @inline final override def dropWhile(p: A => Boolean): List[A] = { @tailrec def loop(xs: List[A]): List[A] = if (xs.isEmpty || !p(xs.head)) xs @@ -282,7 +365,7 @@ sealed abstract class List[+A] extends AbstractSeq[A] loop(this) } - override def span(p: A => Boolean): (List[A], List[A]) = { + @inline final override def span(p: A => Boolean): (List[A], List[A]) = { val b = new ListBuffer[A] var these = this while (!these.isEmpty && p(these.head)) { @@ -292,6 +375,16 @@ sealed abstract class List[+A] extends AbstractSeq[A] (b.toList, these) } + // Overridden with an implementation identical to the inherited one (at this time) + // solely so it can be finalized and thus inlinable. + @inline final override def foreach[U](f: A => U) { + var these = this + while (!these.isEmpty) { + f(these.head) + these = these.tail + } + } + override def reverse: List[A] = { var result: List[A] = Nil var these = this @@ -301,7 +394,7 @@ sealed abstract class List[+A] extends AbstractSeq[A] } result } - + override def foldRight[B](z: B)(op: (A, B) => B): B = reverse.foldLeft(z)((right, left) => op(left, right)) @@ -311,17 +404,9 @@ sealed abstract class List[+A] extends AbstractSeq[A] if (isEmpty) Stream.Empty else new Stream.Cons(head, tail.toStream) - @inline override final - def foreach[B](f: A => B) { - var these = this - while (!these.isEmpty) { - f(these.head) - these = these.tail - } - } - - @deprecated("use `distinct` instead", "2.8.0") - def removeDuplicates: List[A] = distinct + // Create a proxy for Java serialization that allows us to avoid mutation + // during de-serialization. This is the Serialization Proxy Pattern. + protected final def writeReplace(): AnyRef = new List.SerializationProxy(this) } /** The empty list. @@ -352,33 +437,9 @@ case object Nil extends List[Nothing] { * @version 1.0, 15/07/2003 * @since 2.8 */ -@SerialVersionUID(0L - 8476791151983527571L) -final case class ::[B](private var hd: B, private[scala] var tl: List[B]) extends List[B] { - override def head : B = hd +final case class ::[B](override val head: B, private[scala] var tl: List[B]) extends List[B] { override def tail : List[B] = tl override def isEmpty: Boolean = false - - private def readObject(in: ObjectInputStream) { - val firstObject = in.readObject() - hd = firstObject.asInstanceOf[B] - assert(hd != ListSerializeEnd) - var current: ::[B] = this - while (true) in.readObject match { - case ListSerializeEnd => - current.tl = Nil - return - case a => - val list : ::[B] = new ::(a.asInstanceOf[B], Nil) - current.tl = list - current = list - } - } - - private def writeObject(out: ObjectOutputStream) { - var xs: List[B] = this - while (!xs.isEmpty) { out.writeObject(xs.head); xs = xs.tail } - out.writeObject(ListSerializeEnd) - } } /** $factoryInfo @@ -386,9 +447,6 @@ final case class ::[B](private var hd: B, private[scala] var tl: List[B]) extend * @define Coll `List` */ object List extends SeqFactory[List] { - - import scala.collection.{Iterable, Seq, IndexedSeq} - /** $genericCanBuildFromInfo */ implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, List[A]] = ReusableCBF.asInstanceOf[GenericCanBuildFrom[A]] @@ -398,255 +456,39 @@ object List extends SeqFactory[List] { override def empty[A]: List[A] = Nil override def apply[A](xs: A*): List[A] = xs.toList + + private[collection] val partialNotApplied = new Function1[Any, Any] { def apply(x: Any): Any = this } - /** Create a sorted list with element values `v,,>n+1,, = step(v,,n,,)` - * where `v,,0,, = start` and elements are in the range between `start` - * (inclusive) and `end` (exclusive). - * - * @param start the start value of the list - * @param end the end value of the list - * @param step the increment function of the list, which given `v,,n,,`, - * computes `v,,n+1,,`. Must be monotonically increasing - * or decreasing. - * @return the sorted list of all integers in range `[start;end)`. - */ - @deprecated("use `iterate` instead", "2.8.0") - def range(start: Int, end: Int, step: Int => Int): List[Int] = { - val up = step(start) > start - val down = step(start) < start - val b = new ListBuffer[Int] - var i = start - while ((!up || i < end) && (!down || i > end)) { - b += i - val next = step(i) - if (i == next) - throw new IllegalArgumentException("the step function did not make any progress on "+ i) - i = next - } - b.toList - } + @SerialVersionUID(1L) + private class SerializationProxy[A](@transient private var orig: List[A]) extends Serializable { - /** Create a list containing several copies of an element. - * - * @param n the length of the resulting list - * @param elem the element composing the resulting list - * @return a list composed of `n` elements all equal to `elem` - */ - @deprecated("use `fill` instead", "2.8.0") - def make[A](n: Int, elem: A): List[A] = { - val b = new ListBuffer[A] - var i = 0 - while (i < n) { - b += elem - i += 1 - } - b.toList - } - - /** Concatenate all the elements of a given list of lists. - * - * @param xss the list of lists that are to be concatenated - * @return the concatenation of all the lists - */ - @deprecated("use `xss.flatten` instead of `List.flatten(xss)`", "2.8.0") - def flatten[A](xss: List[List[A]]): List[A] = { - val b = new ListBuffer[A] - for (xs <- xss) { - var xc = xs - while (!xc.isEmpty) { - b += xc.head - xc = xc.tail + private def writeObject(out: ObjectOutputStream) { + var xs: List[A] = orig + while (!xs.isEmpty) { + out.writeObject(xs.head) + xs = xs.tail } + out.writeObject(ListSerializeEnd) } - b.toList - } - /** Transforms a list of pairs into a pair of lists. - * - * @param xs the list of pairs to unzip - * @return a pair of lists. - */ - @deprecated("use `xs.unzip` instead of `List.unzip(xs)`", "2.8.0") - def unzip[A,B](xs: List[(A,B)]): (List[A], List[B]) = { - val b1 = new ListBuffer[A] - val b2 = new ListBuffer[B] - var xc = xs - while (!xc.isEmpty) { - b1 += xc.head._1 - b2 += xc.head._2 - xc = xc.tail - } - (b1.toList, b2.toList) - } - - /** Transforms an iterable of pairs into a pair of lists. - * - * @param xs the iterable of pairs to unzip - * @return a pair of lists. - */ - @deprecated("use `xs.unzip` instead of `List.unzip(xs)`", "2.8.0") - def unzip[A,B](xs: Iterable[(A,B)]): (List[A], List[B]) = - xs.foldRight[(List[A], List[B])]((Nil, Nil)) { - case ((x, y), (xs, ys)) => (x :: xs, y :: ys) + // Java serialization calls this before readResolve during de-serialization. + // Read the whole list and store it in `orig`. + private def readObject(in: ObjectInputStream) { + val builder = List.newBuilder[A] + while (true) in.readObject match { + case ListSerializeEnd => + orig = builder.result() + return + case a => + builder += a.asInstanceOf[A] } - - /** - * Returns the `Left` values in the given `Iterable` of `Either`s. - */ - @deprecated("use `xs collect { case Left(x: A) => x }` instead of `List.lefts(xs)`", "2.8.0") - def lefts[A, B](es: Iterable[Either[A, B]]) = - es.foldRight[List[A]](Nil)((e, as) => e match { - case Left(a) => a :: as - case Right(_) => as - }) - - /** - * Returns the `Right` values in the given `Iterable` of `Either`s. - */ - @deprecated("use `xs collect { case Right(x: B) => x }` instead of `List.rights(xs)`", "2.8.0") - def rights[A, B](es: Iterable[Either[A, B]]) = - es.foldRight[List[B]](Nil)((e, bs) => e match { - case Left(_) => bs - case Right(b) => b :: bs - }) - - /** Transforms an Iterable of Eithers into a pair of lists. - * - * @param es the iterable of Eithers to separate - * @return a pair of lists. - */ - @deprecated("use `(for (Left(x) <- es) yield x, for (Right(x) <- es) yield x)` instead", "2.8.0") - def separate[A,B](es: Iterable[Either[A, B]]): (List[A], List[B]) = - es.foldRight[(List[A], List[B])]((Nil, Nil)) { - case (Left(a), (lefts, rights)) => (a :: lefts, rights) - case (Right(b), (lefts, rights)) => (lefts, b :: rights) } - /** Converts an iterator to a list. - * - * @param it the iterator to convert - * @return a list that contains the elements returned by successive - * calls to `it.next` - */ - @deprecated("use `it.toList` instead of `List.toList(it)`", "2.8.0") - def fromIterator[A](it: Iterator[A]): List[A] = it.toList - - /** Converts an array into a list. - * - * @param arr the array to convert - * @return a list that contains the same elements than `arr` - * in the same order - */ - @deprecated("use `array.toList` instead of `List.fromArray(array)`", "2.8.0") - def fromArray[A](arr: Array[A]): List[A] = fromArray(arr, 0, arr.length) - - /** Converts a range of an array into a list. - * - * @param arr the array to convert - * @param start the first index to consider - * @param len the length of the range to convert - * @return a list that contains the same elements than `arr` - * in the same order - */ - @deprecated("use `array.view(start, end).toList` instead of `List.fromArray(array, start, end)`", "2.8.0") - def fromArray[A](arr: Array[A], start: Int, len: Int): List[A] = { - var res: List[A] = Nil - var i = start + len - while (i > start) { - i -= 1 - res = arr(i) :: res - } - res - } - - /** Returns the list resulting from applying the given function `f` - * to corresponding elements of the argument lists. - * - * @param f function to apply to each pair of elements. - * @return `[f(a,,0,,,b,,0,,), ..., f(a,,n,,,b,,n,,)]` if the lists are - * `[a,,0,,, ..., a,,k,,]`, `[b,,0,,, ..., b,,l,,]` and - * `n = min(k,l)` - */ - @deprecated("use `(xs, ys).zipped.map(f)` instead of `List.map2(xs, ys)(f)`", "2.8.0") - def map2[A,B,C](xs: List[A], ys: List[B])(f: (A, B) => C): List[C] = { - val b = new ListBuffer[C] - var xc = xs - var yc = ys - while (!xc.isEmpty && !yc.isEmpty) { - b += f(xc.head, yc.head) - xc = xc.tail - yc = yc.tail - } - b.toList - } - - /** Tests whether the given predicate `p` holds - * for all corresponding elements of the argument lists. - * - * @param f function to apply to each pair of elements. - * @return `(p(a<sub>0</sub>,b<sub>0</sub>) && - * ... && p(a<sub>n</sub>,b<sub>n</sub>))]` - * if the lists are `[a<sub>0</sub>, ..., a<sub>k</sub>]`; - * `[b<sub>0</sub>, ..., b<sub>l</sub>]` - * and `n = min(k,l)` - */ - @deprecated("use `(xs, ys).zipped.forall(f)` instead of `List.forall2(xs, ys)(f)`", "2.8.0") - def forall2[A,B](xs: List[A], ys: List[B])(f: (A, B) => Boolean): Boolean = { - var xc = xs - var yc = ys - while (!xc.isEmpty && !yc.isEmpty) { - if (!f(xc.head, yc.head)) return false - xc = xc.tail - yc = yc.tail - } - true - } - - /** Tests whether the given predicate `p` holds - * for some corresponding elements of the argument lists. - * - * @param f function to apply to each pair of elements. - * @return `n != 0 && (p(a<sub>0</sub>,b<sub>0</sub>) || - * ... || p(a<sub>n</sub>,b<sub>n</sub>))]` if the lists are - * `[a<sub>0</sub>, ..., a<sub>k</sub>]`, - * `[b<sub>0</sub>, ..., b<sub>l</sub>]` and - * `n = min(k,l)` - */ - @deprecated("use `(xs, ys).zipped.exists(f)` instead of `List.exists2(xs, ys)(f)`", "2.8.0") - def exists2[A,B](xs: List[A], ys: List[B])(f: (A, B) => Boolean): Boolean = { - var xc = xs - var yc = ys - while (!xc.isEmpty && !yc.isEmpty) { - if (f(xc.head, yc.head)) return true - xc = xc.tail - yc = yc.tail - } - false - } - - /** Transposes a list of lists. - * pre: All element lists have the same length. - * - * @param xss the list of lists - * @return the transposed list of lists - */ - @deprecated("use `xss.transpose` instead of `List.transpose(xss)`", "2.8.0") - def transpose[A](xss: List[List[A]]): List[List[A]] = { - val buf = new ListBuffer[List[A]] - var yss = xss - while (!yss.head.isEmpty) { - buf += (yss map (_.head)) - yss = (yss map (_.tail)) - } - buf.toList + // Provide the result stored in `orig` for Java serialization + private def readResolve(): AnyRef = orig } } /** Only used for list serialization */ -@SerialVersionUID(0L - 8287891243975527522L) -private[scala] case object ListSerializeStart - -/** Only used for list serialization */ @SerialVersionUID(0L - 8476791151975527571L) private[scala] case object ListSerializeEnd - diff --git a/src/library/scala/collection/immutable/ListMap.scala b/src/library/scala/collection/immutable/ListMap.scala index 75817350e5..7c40e84280 100644 --- a/src/library/scala/collection/immutable/ListMap.scala +++ b/src/library/scala/collection/immutable/ListMap.scala @@ -8,7 +8,8 @@ -package scala.collection +package scala +package collection package immutable import generic._ @@ -48,6 +49,7 @@ object ListMap extends ImmutableMapFactory[ListMap] { * @define willNotTerminateInf */ @SerialVersionUID(301002838095710379L) +@deprecatedInheritance("The semantics of immutable collections makes inheriting from ListMap error-prone.", "2.11.0") class ListMap[A, +B] extends AbstractMap[A, B] with Map[A, B] @@ -121,12 +123,12 @@ extends AbstractMap[A, B] def hasNext = !self.isEmpty def next(): (A,B) = if (!hasNext) throw new NoSuchElementException("next on empty iterator") - else { val res = (self.key, self.value); self = self.tail; res } + else { val res = (self.key, self.value); self = self.next; res } }.toList.reverseIterator protected def key: A = throw new NoSuchElementException("empty map") protected def value: B = throw new NoSuchElementException("empty map") - override def tail: ListMap[A, B] = throw new NoSuchElementException("empty map") + protected def next: ListMap[A, B] = throw new NoSuchElementException("empty map") /** This class represents an entry in the `ListMap`. */ @@ -140,7 +142,7 @@ extends AbstractMap[A, B] override def size: Int = size0(this, 0) // to allow tail recursion and prevent stack overflows - @tailrec private def size0(cur: ListMap[A, B1], acc: Int): Int = if (cur.isEmpty) acc else size0(cur.tail, acc + 1) + @tailrec private def size0(cur: ListMap[A, B1], acc: Int): Int = if (cur.isEmpty) acc else size0(cur.next, acc + 1) /** Is this an empty map? * @@ -156,12 +158,12 @@ extends AbstractMap[A, B] * @return the value associated with the given key. */ override def apply(k: A): B1 = apply0(this, k) - - - @tailrec private def apply0(cur: ListMap[A, B1], k: A): B1 = + + + @tailrec private def apply0(cur: ListMap[A, B1], k: A): B1 = if (cur.isEmpty) throw new NoSuchElementException("key not found: "+k) else if (k == cur.key) cur.value - else apply0(cur.tail, k) + else apply0(cur.next, k) /** Checks if this map maps `key` to a value and return the * value if it exists. @@ -173,14 +175,14 @@ extends AbstractMap[A, B] @tailrec private def get0(cur: ListMap[A, B1], k: A): Option[B1] = if (k == cur.key) Some(cur.value) - else if (cur.tail.nonEmpty) get0(cur.tail, k) else None + else if (cur.next.nonEmpty) get0(cur.next, k) else None /** This method allows one to create a new map with an additional mapping * from `key` to `value`. If the map contains already a mapping for `key`, * it will be overridden by this function. */ override def updated [B2 >: B1](k: A, v: B2): ListMap[A, B2] = { - val m = if (contains(k)) this - k else this + val m = this - k new m.Node[B2](k, v) } @@ -188,33 +190,18 @@ extends AbstractMap[A, B] * If the map does not contain a mapping for the given key, the * method returns the same map. */ - override def - (k: A): ListMap[A, B1] = { - // This definition used to result in stack overflows - // if (k == key) - // next - // else { - // val tail = next - k - // if (tail eq next) this - // else new tail.Node(key, value) - // } - // we use an imperative one instead (and use an auxiliary list to preserve order!): - var cur: ListMap[A, B1] = this - var lst: List[(A, B1)] = Nil - while (cur.nonEmpty) { - if (k != cur.key) lst ::= ((cur.key, cur.value)) - cur = cur.tail - } - var acc = ListMap[A, B1]() - while (lst != Nil) { - val elem = lst.head - val stbl = acc - acc = new stbl.Node(elem._1, elem._2) - lst = lst.tail - } - acc - } - - - override def tail: ListMap[A, B1] = ListMap.this + override def - (k: A): ListMap[A, B1] = remove0(k, this, Nil) + + @tailrec private def remove0(k: A, cur: ListMap[A, B1], acc: List[ListMap[A, B1]]): ListMap[A, B1] = + if (cur.isEmpty) + acc.last + else if (k == cur.key) + (cur.next /: acc) { + case (t, h) => val tt = t; new tt.Node(h.key, h.value) // SI-7459 + } + else + remove0(k, cur.next, cur::acc) + + override protected def next: ListMap[A, B1] = ListMap.this } } diff --git a/src/library/scala/collection/immutable/ListSet.scala b/src/library/scala/collection/immutable/ListSet.scala index 6cf6c4259e..89d1a9640e 100644 --- a/src/library/scala/collection/immutable/ListSet.scala +++ b/src/library/scala/collection/immutable/ListSet.scala @@ -6,7 +6,8 @@ ** |/ ** \* */ -package scala.collection +package scala +package collection package immutable import generic._ @@ -21,10 +22,11 @@ import mutable.{ ListBuffer, Builder } object ListSet extends ImmutableSetFactory[ListSet] { /** setCanBuildFromInfo */ implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, ListSet[A]] = setCanBuildFrom[A] - override def empty[A] = EmptyListSet.asInstanceOf[ListSet[A]] + override def newBuilder[A]: Builder[A, ListSet[A]] = new ListSetBuilder[A] private object EmptyListSet extends ListSet[Any] { } + private[collection] def emptyInstance: ListSet[Any] = EmptyListSet /** A custom builder because forgetfully adding elements one at * a time to a list backed set puts the "squared" in N^2. There is a @@ -63,6 +65,7 @@ object ListSet extends ImmutableSetFactory[ListSet] { * @define mayNotTerminateInf * @define willNotTerminateInf */ +@deprecatedInheritance("The semantics of immutable collections makes inheriting from ListSet error-prone.", "2.11.0") class ListSet[A] extends AbstractSet[A] with Set[A] with GenericSetTemplate[A, ListSet] @@ -75,7 +78,7 @@ class ListSet[A] extends AbstractSet[A] * @return number of set elements. */ override def size: Int = 0 - override def isEmpty: Boolean = true; + override def isEmpty: Boolean = true /** Checks if this set contains element `elem`. * @@ -100,7 +103,7 @@ class ListSet[A] extends AbstractSet[A] */ override def ++(xs: GenTraversableOnce[A]): ListSet[A] = if (xs.isEmpty) this - else (new ListSet.ListSetBuilder(this) ++= xs.seq).result + else (new ListSet.ListSetBuilder(this) ++= xs.seq).result() private[ListSet] def unchecked_+(e: A): ListSet[A] = new Node(e) private[ListSet] def unchecked_outer: ListSet[A] = @@ -120,21 +123,28 @@ class ListSet[A] extends AbstractSet[A] that = that.tail res } - else Iterator.empty.next + else Iterator.empty.next() } /** * @throws Predef.NoSuchElementException */ - override def head: A = throw new NoSuchElementException("Set has no elements"); + override def head: A = throw new NoSuchElementException("Set has no elements") /** * @throws Predef.NoSuchElementException */ - override def tail: ListSet[A] = throw new NoSuchElementException("Next of an empty set"); + override def tail: ListSet[A] = throw new NoSuchElementException("Next of an empty set") override def stringPrefix = "ListSet" + /** Returns this $coll as an immutable set. + * + * A new set will not be built; lazy collections will stay lazy. + */ + @deprecatedOverriding("Immutable sets should do nothing on toSet but return themselves cast as a Set.", "2.11.0") + override def toSet[B >: A]: Set[B] = this.asInstanceOf[Set[B]] + /** Represents an entry in the `ListSet`. */ protected class Node(override val head: A) extends ListSet[A] with Serializable { diff --git a/src/library/scala/collection/immutable/LongMap.scala b/src/library/scala/collection/immutable/LongMap.scala index 2a2910439a..868c0c0f47 100644 --- a/src/library/scala/collection/immutable/LongMap.scala +++ b/src/library/scala/collection/immutable/LongMap.scala @@ -12,6 +12,7 @@ package immutable import scala.collection.generic.{ CanBuildFrom, BitOperations } import scala.collection.mutable.{ Builder, MapBuilder } +import scala.annotation.tailrec /** Utility class for long maps. * @author David MacIver @@ -77,8 +78,6 @@ object LongMap { } } -import LongMap._ - // Iterator over a non-empty LongMap. private[immutable] abstract class LongMapIterator[V, T](it: LongMap[V]) extends AbstractIterator[T] { @@ -98,7 +97,7 @@ private[immutable] abstract class LongMapIterator[V, T](it: LongMap[V]) extends buffer(index) = x.asInstanceOf[AnyRef] index += 1 } - push(it); + push(it) /** * What value do we assign to a tip? @@ -179,7 +178,7 @@ extends AbstractMap[Long, T] */ override final def foreach[U](f: ((Long, T)) => U): Unit = this match { case LongMap.Bin(_, _, left, right) => { left.foreach(f); right.foreach(f) } - case LongMap.Tip(key, value) => f((key, value)); + case LongMap.Tip(key, value) => f((key, value)) case LongMap.Nil => } @@ -206,7 +205,7 @@ extends AbstractMap[Long, T] } /** - * Loop over the keys of the map. The same as keys.foreach(f), but may + * Loop over the values of the map. The same as values.foreach(f), but may * be more efficient. * * @param f The loop body @@ -418,5 +417,20 @@ extends AbstractMap[Long, T] def ++[S >: T](that: LongMap[S]) = this.unionWith[S](that, (key, x, y) => y) + + @tailrec + final def firstKey: Long = this match { + case LongMap.Bin(_, _, l, r) => l.firstKey + case LongMap.Tip(k, v) => k + case LongMap.Nil => sys.error("Empty set") + } + + @tailrec + final def lastKey: Long = this match { + case LongMap.Bin(_, _, l, r) => r.lastKey + case LongMap.Tip(k , v) => k + case LongMap.Nil => sys.error("Empty set") + } + } diff --git a/src/library/scala/collection/immutable/Map.scala b/src/library/scala/collection/immutable/Map.scala index 2ebf5035e1..5178d5a862 100644 --- a/src/library/scala/collection/immutable/Map.scala +++ b/src/library/scala/collection/immutable/Map.scala @@ -7,7 +7,8 @@ \* */ -package scala.collection +package scala +package collection package immutable import generic._ @@ -31,6 +32,12 @@ trait Map[A, +B] extends Iterable[(A, B)] with MapLike[A, B, Map[A, B]] { self => override def empty: Map[A, B] = Map.empty + + /** Returns this $coll as an immutable map. + * + * A new map will not be built; lazy collections will stay lazy. + */ + @deprecatedOverriding("Immutable maps should do nothing on toMap except return themselves cast as a map.", "2.11.0") override def toMap[T, U](implicit ev: (A, B) <:< (T, U)): immutable.Map[T, U] = self.asInstanceOf[immutable.Map[T, U]] @@ -51,7 +58,7 @@ trait Map[A, +B] extends Iterable[(A, B)] * * Invoking transformer methods (e.g. `map`) will not preserve the default value. * - * @param d the function mapping keys to values, used for non-present keys + * @param d default value used for non-present keys * @return a wrapper of the map with a default value */ def withDefaultValue[B1 >: B](d: B1): immutable.Map[A, B1] = new Map.WithDefault[A, B1](this, x => d) @@ -184,4 +191,4 @@ object Map extends ImmutableMapFactory[Map] { } /** Explicit instantiation of the `Map` trait to reduce class file size in subclasses. */ -private[scala] abstract class AbstractMap[A, +B] extends scala.collection.AbstractMap[A, B] with Map[A, B] +abstract class AbstractMap[A, +B] extends scala.collection.AbstractMap[A, B] with Map[A, B] diff --git a/src/library/scala/collection/immutable/MapLike.scala b/src/library/scala/collection/immutable/MapLike.scala index 7e60f07847..94a5b7929a 100644 --- a/src/library/scala/collection/immutable/MapLike.scala +++ b/src/library/scala/collection/immutable/MapLike.scala @@ -6,7 +6,8 @@ ** |/ ** \* */ -package scala.collection +package scala +package collection package immutable import generic._ @@ -85,14 +86,14 @@ self => */ override def ++[B1 >: B](xs: GenTraversableOnce[(A, B1)]): immutable.Map[A, B1] = ((repr: immutable.Map[A, B1]) /: xs.seq) (_ + _) - + /** Filters this map by retaining only keys satisfying a predicate. * @param p the predicate used to test keys * @return an immutable map consisting only of those key value pairs of this map where the key satisfies * the predicate `p`. The resulting map wraps the original map without copying any elements. */ override def filterKeys(p: A => Boolean): Map[A, B] = new FilteredKeys(p) with DefaultMap[A, B] - + /** Transforms this map by applying a function to every retrieved value. * @param f the function used to transform values of this map. * @return a map view which maps every key of this map @@ -123,7 +124,7 @@ self => def transform[C, That](f: (A, B) => C)(implicit bf: CanBuildFrom[This, (A, C), That]): That = { val b = bf(repr) for ((key, value) <- this) b += ((key, f(key, value))) - b.result + b.result() } } diff --git a/src/library/scala/collection/immutable/MapProxy.scala b/src/library/scala/collection/immutable/MapProxy.scala index f3f04ec346..d126b9e7a6 100644 --- a/src/library/scala/collection/immutable/MapProxy.scala +++ b/src/library/scala/collection/immutable/MapProxy.scala @@ -8,7 +8,8 @@ -package scala.collection +package scala +package collection package immutable /** @@ -22,6 +23,7 @@ package immutable * @version 2.0, 31/12/2006 * @since 2.8 */ +@deprecated("Proxying is deprecated due to lack of use and compiler-level support.", "2.11.0") trait MapProxy[A, +B] extends Map[A, B] with MapProxyLike[A, B, Map[A, B]] { override def repr = this private def newProxy[B1 >: B](newSelf: Map[A, B1]): MapProxy[A, B1] = diff --git a/src/library/scala/collection/immutable/NumericRange.scala b/src/library/scala/collection/immutable/NumericRange.scala index d3be299f89..f1ac161e9a 100644 --- a/src/library/scala/collection/immutable/NumericRange.scala +++ b/src/library/scala/collection/immutable/NumericRange.scala @@ -6,12 +6,11 @@ ** |/ ** \* */ - -package scala.collection +package scala +package collection package immutable import mutable.{ Builder, ListBuffer } -import generic._ /** `NumericRange` is a more generic version of the * `Range` class which works with arbitrary types. @@ -81,17 +80,6 @@ extends AbstractSeq[T] with IndexedSeq[T] with Serializable { // to guard against any (most likely illusory) performance drop. They should // be eliminated one way or another. - // Counts how many elements from the start meet the given test. - private def skipCount(p: T => Boolean): Int = { - var current = start - var counted = 0 - - while (counted < length && p(current)) { - counted += 1 - current += step - } - counted - } // Tests whether a number is within the endpoints, without testing // whether it is a member of the sequence (i.e. when step > 1.) private def isWithinBoundaries(elem: T) = !isEmpty && ( @@ -124,21 +112,21 @@ extends AbstractSeq[T] with IndexedSeq[T] with Serializable { if (idx < 0 || idx >= length) throw new IndexOutOfBoundsException(idx.toString) else locationAfterN(idx) } - + import NumericRange.defaultOrdering - + override def min[T1 >: T](implicit ord: Ordering[T1]): T = if (ord eq defaultOrdering(num)) { if (num.signum(step) > 0) start else last } else super.min(ord) - - override def max[T1 >: T](implicit ord: Ordering[T1]): T = + + override def max[T1 >: T](implicit ord: Ordering[T1]): T = if (ord eq defaultOrdering(num)) { if (num.signum(step) > 0) last else start } else super.max(ord) - + // Motivated by the desire for Double ranges with BigDecimal precision, // we need some way to map a Range and get another Range. This can't be // done in any fully general way because Ranges are not arbitrary @@ -182,15 +170,41 @@ extends AbstractSeq[T] with IndexedSeq[T] with Serializable { def containsTyped(x: T): Boolean = isWithinBoundaries(x) && (((x - start) % step) == zero) - override def contains(x: Any): Boolean = + override def contains[A1 >: T](x: A1): Boolean = try containsTyped(x.asInstanceOf[T]) catch { case _: ClassCastException => false } final override def sum[B >: T](implicit num: Numeric[B]): B = { - import num.Ops - if (isEmpty) this.num fromInt 0 - else if (numRangeElements == 1) head - else ((this.num fromInt numRangeElements) * (head + last) / (this.num fromInt 2)) + // arithmetic series formula can be used for regular addition + if ((num eq scala.math.Numeric.IntIsIntegral)|| + (num eq scala.math.Numeric.BigIntIsIntegral)|| + (num eq scala.math.Numeric.ShortIsIntegral)|| + (num eq scala.math.Numeric.ByteIsIntegral)|| + (num eq scala.math.Numeric.CharIsIntegral)|| + (num eq scala.math.Numeric.LongIsIntegral)|| + (num eq scala.math.Numeric.FloatAsIfIntegral)|| + (num eq scala.math.Numeric.BigDecimalIsFractional)|| + (num eq scala.math.Numeric.DoubleAsIfIntegral)) { + val numAsIntegral = num.asInstanceOf[Integral[B]] + import numAsIntegral._ + if (isEmpty) num fromInt 0 + else if (numRangeElements == 1) head + else ((num fromInt numRangeElements) * (head + last) / (num fromInt 2)) + } else { + // user provided custom Numeric, we cannot rely on arithmetic series formula + if (isEmpty) num.zero + else { + var acc = num.zero + var i = head + var idx = 0 + while(idx < length) { + acc = num.plus(acc, i) + i = i + step + idx = idx + 1 + } + acc + } + } } override lazy val hashCode = super.hashCode() @@ -213,7 +227,7 @@ extends AbstractSeq[T] with IndexedSeq[T] with Serializable { /** A companion object for numeric ranges. */ object NumericRange { - + /** Calculates the number of elements in a range given start, end, step, and * whether or not it is inclusive. Throws an exception if step == 0 or * the number of elements exceeds the maximum Int. @@ -227,28 +241,79 @@ object NumericRange { else if (start == end) if (isInclusive) 1 else 0 else if (upward != posStep) 0 else { - val diff = num.minus(end, start) - val jumps = num.toLong(num.quot(diff, step)) - val remainder = num.rem(diff, step) - val longCount = jumps + ( - if (!isInclusive && zero == remainder) 0 else 1 - ) - - /** The edge cases keep coming. Since e.g. - * Long.MaxValue + 1 == Long.MinValue - * we do some more improbable seeming checks lest - * overflow turn up as an empty range. + /* We have to be frightfully paranoid about running out of range. + * We also can't assume that the numbers will fit in a Long. + * We will assume that if a > 0, -a can be represented, and if + * a < 0, -a+1 can be represented. We also assume that if we + * can't fit in Int, we can represent 2*Int.MaxValue+3 (at least). + * And we assume that numbers wrap rather than cap when they overflow. */ - // The second condition contradicts an empty result. - val isOverflow = longCount == 0 && num.lt(num.plus(start, step), end) == upward - - if (longCount > scala.Int.MaxValue || longCount < 0L || isOverflow) { - val word = if (isInclusive) "to" else "until" - val descr = List(start, word, end, "by", step) mkString " " - - throw new IllegalArgumentException(descr + ": seqs cannot contain more than Int.MaxValue elements.") + // Check whether we can short-circuit by deferring to Int range. + val startint = num.toInt(start) + if (start == num.fromInt(startint)) { + val endint = num.toInt(end) + if (end == num.fromInt(endint)) { + val stepint = num.toInt(step) + if (step == num.fromInt(stepint)) { + return { + if (isInclusive) Range.inclusive(startint, endint, stepint).length + else Range (startint, endint, stepint).length + } + } + } + } + // If we reach this point, deferring to Int failed. + // Numbers may be big. + val one = num.one + val limit = num.fromInt(Int.MaxValue) + def check(t: T): T = + if (num.gt(t, limit)) throw new IllegalArgumentException("More than Int.MaxValue elements.") + else t + // If the range crosses zero, it might overflow when subtracted + val startside = num.signum(start) + val endside = num.signum(end) + num.toInt{ + if (startside*endside >= 0) { + // We're sure we can subtract these numbers. + // Note that we do not use .rem because of different conventions for Long and BigInt + val diff = num.minus(end, start) + val quotient = check(num.quot(diff, step)) + val remainder = num.minus(diff, num.times(quotient, step)) + if (!isInclusive && zero == remainder) quotient else check(num.plus(quotient, one)) + } + else { + // We might not even be able to subtract these numbers. + // Jump in three pieces: + // * start to -1 or 1, whichever is closer (waypointA) + // * one step, which will take us at least to 0 (ends at waypointB) + // * there to the end + val negone = num.fromInt(-1) + val startlim = if (posStep) negone else one + val startdiff = num.minus(startlim, start) + val startq = check(num.quot(startdiff, step)) + val waypointA = if (startq == zero) start else num.plus(start, num.times(startq, step)) + val waypointB = num.plus(waypointA, step) + check { + if (num.lt(waypointB, end) != upward) { + // No last piece + if (isInclusive && waypointB == end) num.plus(startq, num.fromInt(2)) + else num.plus(startq, one) + } + else { + // There is a last piece + val enddiff = num.minus(end,waypointB) + val endq = check(num.quot(enddiff, step)) + val last = if (endq == zero) waypointB else num.plus(waypointB, num.times(endq, step)) + // Now we have to tally up all the pieces + // 1 for the initial value + // startq steps to waypointA + // 1 step to waypointB + // endq steps to the end (one less if !isInclusive and last==end) + num.plus(startq, num.plus(endq, if (!isInclusive && last==end) one else num.fromInt(2))) + } + } + } } - longCount.toInt } } @@ -272,7 +337,7 @@ object NumericRange { new Exclusive(start, end, step) def inclusive[T](start: T, end: T, step: T)(implicit num: Integral[T]): Inclusive[T] = new Inclusive(start, end, step) - + private[collection] val defaultOrdering = Map[Numeric[_], Ordering[_]]( Numeric.BigIntIsIntegral -> Ordering.BigInt, Numeric.IntIsIntegral -> Ordering.Int, @@ -284,6 +349,6 @@ object NumericRange { Numeric.DoubleAsIfIntegral -> Ordering.Double, Numeric.BigDecimalAsIfIntegral -> Ordering.BigDecimal ) - + } diff --git a/src/library/scala/collection/immutable/PagedSeq.scala b/src/library/scala/collection/immutable/PagedSeq.scala index 952107bf78..3a64820be6 100644 --- a/src/library/scala/collection/immutable/PagedSeq.scala +++ b/src/library/scala/collection/immutable/PagedSeq.scala @@ -8,7 +8,8 @@ -package scala.collection +package scala +package collection package immutable import java.io._ @@ -30,7 +31,7 @@ object PagedSeq { new PagedSeq[T]((data: Array[T], start: Int, len: Int) => { var i = 0 while (i < len && source.hasNext) { - data(start + i) = source.next + data(start + i) = source.next() i += 1 } if (i == 0) -1 else i @@ -51,7 +52,7 @@ object PagedSeq { if (cnt == len) cnt else (more(data, start + cnt, len - cnt) max 0) + cnt } else if (source.hasNext) { - current = source.next + current = source.next() more(data, start, len) } else -1 new PagedSeq(more(_: Array[Char], _: Int, _: Int)) @@ -125,6 +126,7 @@ import PagedSeq._ * @define mayNotTerminateInf * @define willNotTerminateInf */ +@deprecatedInheritance("The implementation details of paged sequences make inheriting from them unwise.", "2.11.0") class PagedSeq[T: ClassTag] protected( more: (Array[T], Int, Int) => Int, first1: Page[T], @@ -186,7 +188,10 @@ extends scala.collection.AbstractSeq[T] val s = start + _start val e = if (_end == UndeterminedEnd) _end else start + _end var f = first1 - while (f.end <= s && !f.isLast) f = f.next + while (f.end <= s && !f.isLast) { + if (f.next eq null) f.addMore(more) + f = f.next + } new PagedSeq(more, f, s, e) } diff --git a/src/library/scala/collection/immutable/Queue.scala b/src/library/scala/collection/immutable/Queue.scala index 7d2ff95792..264304db68 100644 --- a/src/library/scala/collection/immutable/Queue.scala +++ b/src/library/scala/collection/immutable/Queue.scala @@ -6,7 +6,8 @@ ** |/ ** \* */ -package scala.collection +package scala +package collection package immutable import generic._ @@ -37,6 +38,7 @@ import scala.annotation.tailrec */ @SerialVersionUID(-7622936493364270175L) +@deprecatedInheritance("The implementation details of immutable queues make inheriting from them unwise.", "2.11.0") class Queue[+A] protected(protected val in: List[A], protected val out: List[A]) extends AbstractSeq[A] with LinearSeq[A] @@ -87,6 +89,16 @@ class Queue[+A] protected(protected val in: List[A], protected val out: List[A]) */ override def length = in.length + out.length + override def +:[B >: A, That](elem: B)(implicit bf: CanBuildFrom[Queue[A], B, That]): That = bf match { + case _: Queue.GenericCanBuildFrom[_] => new Queue(in, elem :: out).asInstanceOf[That] + case _ => super.+:(elem)(bf) + } + + override def :+[B >: A, That](elem: B)(implicit bf: CanBuildFrom[Queue[A], B, That]): That = bf match { + case _: Queue.GenericCanBuildFrom[_] => enqueue(elem).asInstanceOf[That] + case _ => super.:+(elem)(bf) + } + /** Creates a new queue with element added at the end * of the old queue. * @@ -117,6 +129,13 @@ class Queue[+A] protected(protected val in: List[A], protected val out: List[A]) case _ => throw new NoSuchElementException("dequeue on empty queue") } + /** Optionally retrieves the first element and a queue of the remaining elements. + * + * @return A tuple of the first element of the queue, and a new queue with this element removed. + * If the queue is empty, `None` is returned. + */ + def dequeueOption: Option[(A, Queue[A])] = if(isEmpty) None else Some(dequeue) + /** Returns the first element in the queue, or throws an error if there * is no element contained in the queue. * diff --git a/src/library/scala/collection/immutable/Range.scala b/src/library/scala/collection/immutable/Range.scala index 802e16605d..26ccd09803 100644 --- a/src/library/scala/collection/immutable/Range.scala +++ b/src/library/scala/collection/immutable/Range.scala @@ -7,7 +7,8 @@ \* */ -package scala.collection.immutable +package scala +package collection.immutable import scala.collection.parallel.immutable.ParRange @@ -22,6 +23,15 @@ import scala.collection.parallel.immutable.ParRange * println(r2.length) // = 5 * }}} * + * Ranges that contain more than `Int.MaxValue` elements can be created, but + * these overfull ranges have only limited capabilities. Any method that + * could require a collection of over `Int.MaxValue` length to be created, or + * could be asked to index beyond `Int.MaxValue` elements will throw an + * exception. Overfull ranges can safely be reduced in size by changing + * the step size (e.g. `by 3`) or taking/dropping elements. `contains`, + * `equals`, and access to the ends of the range (`head`, `last`, `tail`, + * `init`) are also permitted on overfull ranges. + * * @param start the start of this range. * @param end the exclusive end of the range. * @param step the step for the range. @@ -41,6 +51,7 @@ import scala.collection.parallel.immutable.ParRange * and its complexity is O(1). */ @SerialVersionUID(7618862778670199309L) +@deprecatedInheritance("The implementation details of Range makes inheriting from it unwise.", "2.11.0") class Range(val start: Int, val end: Int, val step: Int) extends scala.collection.AbstractSeq[Int] with IndexedSeq[Int] @@ -64,6 +75,7 @@ extends scala.collection.AbstractSeq[Int] || (start < end && step < 0) || (start == end && !isInclusive) ) + @deprecated("This method will be made private, use `length` instead.", "2.11") final val numRangeElements: Int = { if (step == 0) throw new IllegalArgumentException("step cannot be 0.") else if (isEmpty) 0 @@ -73,21 +85,38 @@ extends scala.collection.AbstractSeq[Int] else len.toInt } } - final val lastElement = start + (numRangeElements - 1) * step - final val terminalElement = start + numRangeElements * step + @deprecated("This method will be made private, use `last` instead.", "2.11") + final val lastElement = + if (isEmpty) start - step + else step match { + case 1 => if (isInclusive) end else end-1 + case -1 => if (isInclusive) end else end+1 + case _ => + val remainder = (gap % step).toInt + if (remainder != 0) end - remainder + else if (isInclusive) end + else end - step + } + + @deprecated("This method will be made private.", "2.11") + final val terminalElement = lastElement + step + /** The last element of this range. This method will return the correct value + * even if there are too many elements to iterate over. + */ override def last = if (isEmpty) Nil.last else lastElement + override def head = if (isEmpty) Nil.head else start override def min[A1 >: Int](implicit ord: Ordering[A1]): Int = if (ord eq Ordering.Int) { - if (step > 0) start + if (step > 0) head else last } else super.min(ord) override def max[A1 >: Int](implicit ord: Ordering[A1]): Int = if (ord eq Ordering.Int) { if (step > 0) last - else start + else head } else super.max(ord) protected def copy(start: Int, end: Int, step: Int): Range = new Range(start, end, step) @@ -111,21 +140,6 @@ extends scala.collection.AbstractSeq[Int] fail() } - def validateRangeBoundaries(f: Int => Any): Boolean = { - validateMaxLength() - - start != Int.MinValue || end != Int.MinValue || { - var count = 0 - var num = start - while (count < numRangeElements) { - f(num) - count += 1 - num += step - } - false - } - } - final def apply(idx: Int): Int = { validateMaxLength() if (idx < 0 || idx >= numRangeElements) throw new IndexOutOfBoundsException(idx.toString) @@ -133,14 +147,19 @@ extends scala.collection.AbstractSeq[Int] } @inline final override def foreach[@specialized(Unit) U](f: Int => U) { - if (validateRangeBoundaries(f)) { - var i = start - val terminal = terminalElement - val step = this.step - while (i != terminal) { - f(i) - i += step - } + validateMaxLength() + val isCommonCase = (start != Int.MinValue || end != Int.MinValue) + var i = start + var count = 0 + val terminal = terminalElement + val step = this.step + while( + if(isCommonCase) { i != terminal } + else { count < numRangeElements } + ) { + f(i) + count += 1 + i += step } } @@ -153,8 +172,12 @@ extends scala.collection.AbstractSeq[Int] */ final override def take(n: Int): Range = ( if (n <= 0 || isEmpty) newEmptyRange(start) - else if (n >= numRangeElements) this - else new Range.Inclusive(start, locationAfterN(n - 1), step) + else if (n >= numRangeElements && numRangeElements >= 0) this + else { + // May have more than Int.MaxValue elements in range (numRangeElements < 0) + // but the logic is the same either way: take the first n + new Range.Inclusive(start, locationAfterN(n - 1), step) + } ) /** Creates a new range containing all the elements of this range except the first `n` elements. @@ -166,8 +189,12 @@ extends scala.collection.AbstractSeq[Int] */ final override def drop(n: Int): Range = ( if (n <= 0 || isEmpty) this - else if (n >= numRangeElements) newEmptyRange(end) - else copy(locationAfterN(n), end, step) + else if (n >= numRangeElements && numRangeElements >= 0) newEmptyRange(end) + else { + // May have more than Int.MaxValue elements (numRangeElements < 0) + // but the logic is the same either way: go forwards n steps, keep the rest + copy(locationAfterN(n), end, step) + } ) /** Creates a new range containing all the elements of this range except the last one. @@ -196,23 +223,17 @@ extends scala.collection.AbstractSeq[Int] drop(1) } - // Counts how many elements from the start meet the given test. - private def skipCount(p: Int => Boolean): Int = { - var current = start - var counted = 0 - - while (counted < numRangeElements && p(current)) { - counted += 1 - current += step + // Advance from the start while we meet the given test + private def argTakeWhile(p: Int => Boolean): Long = { + if (isEmpty) start + else { + var current = start + val stop = last + while (current != stop && p(current)) current += step + if (current != stop || !p(current)) current + else current.toLong + step } - counted } - // Tests whether a number is within the endpoints, without testing - // whether it is a member of the sequence (i.e. when step > 1.) - private def isWithinBoundaries(elem: Int) = !isEmpty && ( - (step > 0 && start <= elem && elem <= last ) || - (step < 0 && last <= elem && elem <= start) - ) // Methods like apply throw exceptions on invalid n, but methods like take/drop // are forgiving: therefore the checks are with the methods. private def locationAfterN(n: Int) = start + (step * n) @@ -223,9 +244,33 @@ extends scala.collection.AbstractSeq[Int] // based on the given value. private def newEmptyRange(value: Int) = new Range(value, value, step) - final override def takeWhile(p: Int => Boolean): Range = take(skipCount(p)) - final override def dropWhile(p: Int => Boolean): Range = drop(skipCount(p)) - final override def span(p: Int => Boolean): (Range, Range) = splitAt(skipCount(p)) + final override def takeWhile(p: Int => Boolean): Range = { + val stop = argTakeWhile(p) + if (stop==start) newEmptyRange(start) + else { + val x = (stop - step).toInt + if (x == last) this + else new Range.Inclusive(start, x, step) + } + } + final override def dropWhile(p: Int => Boolean): Range = { + val stop = argTakeWhile(p) + if (stop == start) this + else { + val x = (stop - step).toInt + if (x == last) newEmptyRange(last) + else new Range.Inclusive(x + step, last, step) + } + } + final override def span(p: Int => Boolean): (Range, Range) = { + val border = argTakeWhile(p) + if (border == start) (newEmptyRange(start), this) + else { + val x = (border - step).toInt + if (x == last) (this, newEmptyRange(last)) + else (new Range.Inclusive(start, x, step), new Range.Inclusive(x+step, last, step)) + } + } /** Creates a pair of new ranges, first consisting of elements before `n`, and the second * of elements after `n`. @@ -238,13 +283,32 @@ extends scala.collection.AbstractSeq[Int] * * $doesNotUseBuilders */ - final override def takeRight(n: Int): Range = drop(numRangeElements - n) + final override def takeRight(n: Int): Range = { + if (n <= 0) newEmptyRange(start) + else if (numRangeElements >= 0) drop(numRangeElements - n) + else { + // Need to handle over-full range separately + val y = last + val x = y - step.toLong*(n-1) + if ((step > 0 && x < start) || (step < 0 && x > start)) this + else new Range.Inclusive(x.toInt, y, step) + } + } /** Creates a new range consisting of the initial `length - n` elements of the range. * * $doesNotUseBuilders */ - final override def dropRight(n: Int): Range = take(numRangeElements - n) + final override def dropRight(n: Int): Range = { + if (n <= 0) this + else if (numRangeElements >= 0) take(numRangeElements - n) + else { + // Need to handle over-full range separately + val y = last - step.toInt*n + if ((step > 0 && y < start) || (step < 0 && y > start)) newEmptyRange(start) + else new Range.Inclusive(start, y.toInt, step) + } + } /** Returns the reverse of this range. * @@ -260,12 +324,37 @@ extends scala.collection.AbstractSeq[Int] if (isInclusive) this else new Range.Inclusive(start, end, step) - final def contains(x: Int) = isWithinBoundaries(x) && ((x - start) % step == 0) + final def contains(x: Int) = { + if (x==end && !isInclusive) false + else if (step > 0) { + if (x < start || x > end) false + else (step == 1) || (((x - start) % step) == 0) + } + else { + if (x < end || x > start) false + else (step == -1) || (((x - start) % step) == 0) + } + } final override def sum[B >: Int](implicit num: Numeric[B]): Int = { - if (isEmpty) 0 - else if (numRangeElements == 1) head - else (numRangeElements.toLong * (head + last) / 2).toInt + if (num eq scala.math.Numeric.IntIsIntegral) { + // this is normal integer range with usual addition. arithmetic series formula can be used + if (isEmpty) 0 + else if (numRangeElements == 1) head + else (numRangeElements.toLong * (head + last) / 2).toInt + } else { + // user provided custom Numeric, we cannot rely on arithmetic series formula + if (isEmpty) num.toInt(num.zero) + else { + var acc = num.zero + var i = head + while(i != terminalElement) { + acc = num.plus(acc, i) + i = i + step + } + num.toInt(acc) + } + } } override def toIterable = this @@ -274,9 +363,15 @@ extends scala.collection.AbstractSeq[Int] override def equals(other: Any) = other match { case x: Range => - (x canEqual this) && (length == x.length) && ( - isEmpty || // all empty sequences are equal - (start == x.start && last == x.last) // same length and same endpoints implies equality + // Note: this must succeed for overfull ranges (length > Int.MaxValue) + (x canEqual this) && ( + isEmpty || // all empty sequences are equal + (start == x.start && { // Otherwise, must have same start + val l0 = last + (l0 == x.last && ( // And same end + start == l0 || step == x.step // And either the same step, or not take any steps + )) + }) ) case _ => super.equals(other) @@ -286,7 +381,8 @@ extends scala.collection.AbstractSeq[Int] */ override def toString() = { - val endStr = if (numRangeElements > Range.MAX_PRINT) ", ... )" else ")" + val endStr = + if (numRangeElements > Range.MAX_PRINT || (!isEmpty && numRangeElements < 0)) ", ... )" else ")" take(Range.MAX_PRINT).mkString("Range(", ", ", endStr) } } @@ -325,7 +421,7 @@ object Range { } } def count(start: Int, end: Int, step: Int): Int = - count(start, end, step, false) + count(start, end, step, isInclusive = false) class Inclusive(start: Int, end: Int, step: Int) extends Range(start, end, step) { // override def par = new ParRange(this) diff --git a/src/library/scala/collection/immutable/RedBlack.scala b/src/library/scala/collection/immutable/RedBlack.scala deleted file mode 100644 index 9739e8f3f3..0000000000 --- a/src/library/scala/collection/immutable/RedBlack.scala +++ /dev/null @@ -1,293 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2005-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - - -package scala -package collection -package immutable - -/** Old base class that was used by previous implementations of `TreeMaps` and `TreeSets`. - * - * Deprecated due to various performance bugs (see [[https://issues.scala-lang.org/browse/SI-5331 SI-5331]] for more information). - * - * @since 2.3 - */ -@deprecated("use `TreeMap` or `TreeSet` instead", "2.10.0") -@SerialVersionUID(8691885935445612921L) -abstract class RedBlack[A] extends Serializable { - - def isSmaller(x: A, y: A): Boolean - - private def blacken[B](t: Tree[B]): Tree[B] = t match { - case RedTree(k, v, l, r) => BlackTree(k, v, l, r) - case t => t - } - private def mkTree[B](isBlack: Boolean, k: A, v: B, l: Tree[B], r: Tree[B]) = - if (isBlack) BlackTree(k, v, l, r) else RedTree(k, v, l, r) - - abstract class Tree[+B] extends Serializable { - def isEmpty: Boolean - def isBlack: Boolean - def lookup(x: A): Tree[B] - def update[B1 >: B](k: A, v: B1): Tree[B1] = blacken(upd(k, v)) - def delete(k: A): Tree[B] = blacken(del(k)) - def range(from: Option[A], until: Option[A]): Tree[B] = blacken(rng(from, until)) - def foreach[U](f: (A, B) => U) - def toStream: Stream[(A,B)] - def iterator: Iterator[(A, B)] - def upd[B1 >: B](k: A, v: B1): Tree[B1] - def del(k: A): Tree[B] - def smallest: NonEmpty[B] - def rng(from: Option[A], until: Option[A]): Tree[B] - def first : A - def last : A - def count : Int - } - abstract class NonEmpty[+B] extends Tree[B] with Serializable { - def isEmpty = false - def key: A - def value: B - def left: Tree[B] - def right: Tree[B] - def lookup(k: A): Tree[B] = - if (isSmaller(k, key)) left.lookup(k) - else if (isSmaller(key, k)) right.lookup(k) - else this - private[this] def balanceLeft[B1 >: B](isBlack: Boolean, z: A, zv: B, l: Tree[B1], d: Tree[B1])/*: NonEmpty[B1]*/ = l match { - case RedTree(y, yv, RedTree(x, xv, a, b), c) => - RedTree(y, yv, BlackTree(x, xv, a, b), BlackTree(z, zv, c, d)) - case RedTree(x, xv, a, RedTree(y, yv, b, c)) => - RedTree(y, yv, BlackTree(x, xv, a, b), BlackTree(z, zv, c, d)) - case _ => - mkTree(isBlack, z, zv, l, d) - } - private[this] def balanceRight[B1 >: B](isBlack: Boolean, x: A, xv: B, a: Tree[B1], r: Tree[B1])/*: NonEmpty[B1]*/ = r match { - case RedTree(z, zv, RedTree(y, yv, b, c), d) => - RedTree(y, yv, BlackTree(x, xv, a, b), BlackTree(z, zv, c, d)) - case RedTree(y, yv, b, RedTree(z, zv, c, d)) => - RedTree(y, yv, BlackTree(x, xv, a, b), BlackTree(z, zv, c, d)) - case _ => - mkTree(isBlack, x, xv, a, r) - } - def upd[B1 >: B](k: A, v: B1): Tree[B1] = { - if (isSmaller(k, key)) balanceLeft(isBlack, key, value, left.upd(k, v), right) - else if (isSmaller(key, k)) balanceRight(isBlack, key, value, left, right.upd(k, v)) - else mkTree(isBlack, k, v, left, right) - } - // Based on Stefan Kahrs' Haskell version of Okasaki's Red&Black Trees - // http://www.cse.unsw.edu.au/~dons/data/RedBlackTree.html - def del(k: A): Tree[B] = { - def balance(x: A, xv: B, tl: Tree[B], tr: Tree[B]) = (tl, tr) match { - case (RedTree(y, yv, a, b), RedTree(z, zv, c, d)) => - RedTree(x, xv, BlackTree(y, yv, a, b), BlackTree(z, zv, c, d)) - case (RedTree(y, yv, RedTree(z, zv, a, b), c), d) => - RedTree(y, yv, BlackTree(z, zv, a, b), BlackTree(x, xv, c, d)) - case (RedTree(y, yv, a, RedTree(z, zv, b, c)), d) => - RedTree(z, zv, BlackTree(y, yv, a, b), BlackTree(x, xv, c, d)) - case (a, RedTree(y, yv, b, RedTree(z, zv, c, d))) => - RedTree(y, yv, BlackTree(x, xv, a, b), BlackTree(z, zv, c, d)) - case (a, RedTree(y, yv, RedTree(z, zv, b, c), d)) => - RedTree(z, zv, BlackTree(x, xv, a, b), BlackTree(y, yv, c, d)) - case (a, b) => - BlackTree(x, xv, a, b) - } - def subl(t: Tree[B]) = t match { - case BlackTree(x, xv, a, b) => RedTree(x, xv, a, b) - case _ => sys.error("Defect: invariance violation; expected black, got "+t) - } - def balLeft(x: A, xv: B, tl: Tree[B], tr: Tree[B]) = (tl, tr) match { - case (RedTree(y, yv, a, b), c) => - RedTree(x, xv, BlackTree(y, yv, a, b), c) - case (bl, BlackTree(y, yv, a, b)) => - balance(x, xv, bl, RedTree(y, yv, a, b)) - case (bl, RedTree(y, yv, BlackTree(z, zv, a, b), c)) => - RedTree(z, zv, BlackTree(x, xv, bl, a), balance(y, yv, b, subl(c))) - case _ => sys.error("Defect: invariance violation at "+right) - } - def balRight(x: A, xv: B, tl: Tree[B], tr: Tree[B]) = (tl, tr) match { - case (a, RedTree(y, yv, b, c)) => - RedTree(x, xv, a, BlackTree(y, yv, b, c)) - case (BlackTree(y, yv, a, b), bl) => - balance(x, xv, RedTree(y, yv, a, b), bl) - case (RedTree(y, yv, a, BlackTree(z, zv, b, c)), bl) => - RedTree(z, zv, balance(y, yv, subl(a), b), BlackTree(x, xv, c, bl)) - case _ => sys.error("Defect: invariance violation at "+left) - } - def delLeft = left match { - case _: BlackTree[_] => balLeft(key, value, left.del(k), right) - case _ => RedTree(key, value, left.del(k), right) - } - def delRight = right match { - case _: BlackTree[_] => balRight(key, value, left, right.del(k)) - case _ => RedTree(key, value, left, right.del(k)) - } - def append(tl: Tree[B], tr: Tree[B]): Tree[B] = (tl, tr) match { - case (Empty, t) => t - case (t, Empty) => t - case (RedTree(x, xv, a, b), RedTree(y, yv, c, d)) => - append(b, c) match { - case RedTree(z, zv, bb, cc) => RedTree(z, zv, RedTree(x, xv, a, bb), RedTree(y, yv, cc, d)) - case bc => RedTree(x, xv, a, RedTree(y, yv, bc, d)) - } - case (BlackTree(x, xv, a, b), BlackTree(y, yv, c, d)) => - append(b, c) match { - case RedTree(z, zv, bb, cc) => RedTree(z, zv, BlackTree(x, xv, a, bb), BlackTree(y, yv, cc, d)) - case bc => balLeft(x, xv, a, BlackTree(y, yv, bc, d)) - } - case (a, RedTree(x, xv, b, c)) => RedTree(x, xv, append(a, b), c) - case (RedTree(x, xv, a, b), c) => RedTree(x, xv, a, append(b, c)) - } - // RedBlack is neither A : Ordering[A], nor A <% Ordered[A] - k match { - case _ if isSmaller(k, key) => delLeft - case _ if isSmaller(key, k) => delRight - case _ => append(left, right) - } - } - - def smallest: NonEmpty[B] = if (left.isEmpty) this else left.smallest - - def toStream: Stream[(A,B)] = - left.toStream ++ Stream((key,value)) ++ right.toStream - - def iterator: Iterator[(A, B)] = - left.iterator ++ Iterator.single(Pair(key, value)) ++ right.iterator - - def foreach[U](f: (A, B) => U) { - left foreach f - f(key, value) - right foreach f - } - - override def rng(from: Option[A], until: Option[A]): Tree[B] = { - if (from == None && until == None) return this - if (from != None && isSmaller(key, from.get)) return right.rng(from, until); - if (until != None && (isSmaller(until.get,key) || !isSmaller(key,until.get))) - return left.rng(from, until); - val newLeft = left.rng(from, None) - val newRight = right.rng(None, until) - if ((newLeft eq left) && (newRight eq right)) this - else if (newLeft eq Empty) newRight.upd(key, value); - else if (newRight eq Empty) newLeft.upd(key, value); - else rebalance(newLeft, newRight) - } - - // The zipper returned might have been traversed left-most (always the left child) - // or right-most (always the right child). Left trees are traversed right-most, - // and right trees are traversed leftmost. - - // Returns the zipper for the side with deepest black nodes depth, a flag - // indicating whether the trees were unbalanced at all, and a flag indicating - // whether the zipper was traversed left-most or right-most. - - // If the trees were balanced, returns an empty zipper - private[this] def compareDepth(left: Tree[B], right: Tree[B]): (List[NonEmpty[B]], Boolean, Boolean, Int) = { - // Once a side is found to be deeper, unzip it to the bottom - def unzip(zipper: List[NonEmpty[B]], leftMost: Boolean): List[NonEmpty[B]] = { - val next = if (leftMost) zipper.head.left else zipper.head.right - next match { - case node: NonEmpty[_] => unzip(node :: zipper, leftMost) - case Empty => zipper - } - } - - // Unzip left tree on the rightmost side and right tree on the leftmost side until one is - // found to be deeper, or the bottom is reached - def unzipBoth(left: Tree[B], - right: Tree[B], - leftZipper: List[NonEmpty[B]], - rightZipper: List[NonEmpty[B]], - smallerDepth: Int): (List[NonEmpty[B]], Boolean, Boolean, Int) = (left, right) match { - case (l @ BlackTree(_, _, _, _), r @ BlackTree(_, _, _, _)) => - unzipBoth(l.right, r.left, l :: leftZipper, r :: rightZipper, smallerDepth + 1) - case (l @ RedTree(_, _, _, _), r @ RedTree(_, _, _, _)) => - unzipBoth(l.right, r.left, l :: leftZipper, r :: rightZipper, smallerDepth) - case (_, r @ RedTree(_, _, _, _)) => - unzipBoth(left, r.left, leftZipper, r :: rightZipper, smallerDepth) - case (l @ RedTree(_, _, _, _), _) => - unzipBoth(l.right, right, l :: leftZipper, rightZipper, smallerDepth) - case (Empty, Empty) => - (Nil, true, false, smallerDepth) - case (Empty, r @ BlackTree(_, _, _, _)) => - val leftMost = true - (unzip(r :: rightZipper, leftMost), false, leftMost, smallerDepth) - case (l @ BlackTree(_, _, _, _), Empty) => - val leftMost = false - (unzip(l :: leftZipper, leftMost), false, leftMost, smallerDepth) - } - unzipBoth(left, right, Nil, Nil, 0) - } - - private[this] def rebalance(newLeft: Tree[B], newRight: Tree[B]) = { - // This is like drop(n-1), but only counting black nodes - def findDepth(zipper: List[NonEmpty[B]], depth: Int): List[NonEmpty[B]] = zipper match { - case BlackTree(_, _, _, _) :: tail => - if (depth == 1) zipper else findDepth(tail, depth - 1) - case _ :: tail => findDepth(tail, depth) - case Nil => sys.error("Defect: unexpected empty zipper while computing range") - } - - // Blackening the smaller tree avoids balancing problems on union; - // this can't be done later, though, or it would change the result of compareDepth - val blkNewLeft = blacken(newLeft) - val blkNewRight = blacken(newRight) - val (zipper, levelled, leftMost, smallerDepth) = compareDepth(blkNewLeft, blkNewRight) - - if (levelled) { - BlackTree(key, value, blkNewLeft, blkNewRight) - } else { - val zipFrom = findDepth(zipper, smallerDepth) - val union = if (leftMost) { - RedTree(key, value, blkNewLeft, zipFrom.head) - } else { - RedTree(key, value, zipFrom.head, blkNewRight) - } - val zippedTree = zipFrom.tail.foldLeft(union: Tree[B]) { (tree, node) => - if (leftMost) - balanceLeft(node.isBlack, node.key, node.value, tree, node.right) - else - balanceRight(node.isBlack, node.key, node.value, node.left, tree) - } - zippedTree - } - } - def first = if (left .isEmpty) key else left.first - def last = if (right.isEmpty) key else right.last - def count = 1 + left.count + right.count - } - case object Empty extends Tree[Nothing] { - def isEmpty = true - def isBlack = true - def lookup(k: A): Tree[Nothing] = this - def upd[B](k: A, v: B): Tree[B] = RedTree(k, v, Empty, Empty) - def del(k: A): Tree[Nothing] = this - def smallest: NonEmpty[Nothing] = throw new NoSuchElementException("empty map") - def iterator: Iterator[(A, Nothing)] = Iterator.empty - def toStream: Stream[(A,Nothing)] = Stream.empty - - def foreach[U](f: (A, Nothing) => U) {} - - def rng(from: Option[A], until: Option[A]) = this - def first = throw new NoSuchElementException("empty map") - def last = throw new NoSuchElementException("empty map") - def count = 0 - } - case class RedTree[+B](override val key: A, - override val value: B, - override val left: Tree[B], - override val right: Tree[B]) extends NonEmpty[B] { - def isBlack = false - } - case class BlackTree[+B](override val key: A, - override val value: B, - override val left: Tree[B], - override val right: Tree[B]) extends NonEmpty[B] { - def isBlack = true - } -} diff --git a/src/library/scala/collection/immutable/RedBlackTree.scala b/src/library/scala/collection/immutable/RedBlackTree.scala index 0254e9ca3a..0dad106b29 100644 --- a/src/library/scala/collection/immutable/RedBlackTree.scala +++ b/src/library/scala/collection/immutable/RedBlackTree.scala @@ -18,19 +18,19 @@ import scala.annotation.meta.getter /** An object containing the RedBlack tree implementation used by for `TreeMaps` and `TreeSets`. * * Implementation note: since efficiency is important for data structures this implementation - * uses <code>null</code> to represent empty trees. This also means pattern matching cannot + * uses `null` to represent empty trees. This also means pattern matching cannot * easily be used. The API represented by the RedBlackTree object tries to hide these * optimizations behind a reasonably clean API. * * @since 2.10 */ -private[immutable] +private[collection] object RedBlackTree { def isEmpty(tree: Tree[_, _]): Boolean = tree eq null - def contains[A](tree: Tree[A, _], x: A)(implicit ordering: Ordering[A]): Boolean = lookup(tree, x) ne null - def get[A, B](tree: Tree[A, B], x: A)(implicit ordering: Ordering[A]): Option[B] = lookup(tree, x) match { + def contains[A: Ordering](tree: Tree[A, _], x: A): Boolean = lookup(tree, x) ne null + def get[A: Ordering, B](tree: Tree[A, B], x: A): Option[B] = lookup(tree, x) match { case null => None case tree => Some(tree.value) } @@ -44,8 +44,27 @@ object RedBlackTree { } def count(tree: Tree[_, _]) = if (tree eq null) 0 else tree.count - def update[A, B, B1 >: B](tree: Tree[A, B], k: A, v: B1, overwrite: Boolean)(implicit ordering: Ordering[A]): Tree[A, B1] = blacken(upd(tree, k, v, overwrite)) - def delete[A, B](tree: Tree[A, B], k: A)(implicit ordering: Ordering[A]): Tree[A, B] = blacken(del(tree, k)) + /** + * Count all the nodes with keys greater than or equal to the lower bound and less than the upper bound. + * The two bounds are optional. + */ + def countInRange[A](tree: Tree[A, _], from: Option[A], to:Option[A])(implicit ordering: Ordering[A]) : Int = + if (tree eq null) 0 else + (from, to) match { + // with no bounds use this node's count + case (None, None) => tree.count + // if node is less than the lower bound, try the tree on the right, it might be in range + case (Some(lb), _) if ordering.lt(tree.key, lb) => countInRange(tree.right, from, to) + // if node is greater than or equal to the upper bound, try the tree on the left, it might be in range + case (_, Some(ub)) if ordering.gteq(tree.key, ub) => countInRange(tree.left, from, to) + // node is in range so the tree on the left will all be less than the upper bound and the tree on the + // right will all be greater than or equal to the lower bound. So 1 for this node plus + // count the subtrees by stripping off the bounds that we don't need any more + case _ => 1 + countInRange(tree.left, from, None) + countInRange(tree.right, None, to) + + } + def update[A: Ordering, B, B1 >: B](tree: Tree[A, B], k: A, v: B1, overwrite: Boolean): Tree[A, B1] = blacken(upd(tree, k, v, overwrite)) + def delete[A: Ordering, B](tree: Tree[A, B], k: A): Tree[A, B] = blacken(del(tree, k)) def rangeImpl[A: Ordering, B](tree: Tree[A, B], from: Option[A], until: Option[A]): Tree[A, B] = (from, until) match { case (Some(from), Some(until)) => this.range(tree, from, until) case (Some(from), None) => this.from(tree, from) @@ -74,20 +93,26 @@ object RedBlackTree { result } - def foreach[A, B, U](tree: Tree[A, B], f: ((A, B)) => U): Unit = if (tree ne null) { - if (tree.left ne null) foreach(tree.left, f) + + def foreach[A,B,U](tree:Tree[A,B], f:((A,B)) => U):Unit = if (tree ne null) _foreach(tree,f) + + private[this] def _foreach[A, B, U](tree: Tree[A, B], f: ((A, B)) => U) { + if (tree.left ne null) _foreach(tree.left, f) f((tree.key, tree.value)) - if (tree.right ne null) foreach(tree.right, f) + if (tree.right ne null) _foreach(tree.right, f) } - def foreachKey[A, U](tree: Tree[A, _], f: A => U): Unit = if (tree ne null) { - if (tree.left ne null) foreachKey(tree.left, f) - f(tree.key) - if (tree.right ne null) foreachKey(tree.right, f) + + def foreachKey[A, U](tree:Tree[A,_], f: A => U):Unit = if (tree ne null) _foreachKey(tree,f) + + private[this] def _foreachKey[A, U](tree: Tree[A, _], f: A => U) { + if (tree.left ne null) _foreachKey(tree.left, f) + f((tree.key)) + if (tree.right ne null) _foreachKey(tree.right, f) } - def iterator[A, B](tree: Tree[A, B]): Iterator[(A, B)] = new EntriesIterator(tree) - def keysIterator[A, _](tree: Tree[A, _]): Iterator[A] = new KeysIterator(tree) - def valuesIterator[_, B](tree: Tree[_, B]): Iterator[B] = new ValuesIterator(tree) + def iterator[A: Ordering, B](tree: Tree[A, B], start: Option[A] = None): Iterator[(A, B)] = new EntriesIterator(tree, start) + def keysIterator[A: Ordering](tree: Tree[A, _], start: Option[A] = None): Iterator[A] = new KeysIterator(tree, start) + def valuesIterator[A: Ordering, B](tree: Tree[A, B], start: Option[A] = None): Iterator[B] = new ValuesIterator(tree, start) @tailrec def nth[A, B](tree: Tree[A, B], n: Int): Tree[A, B] = { @@ -227,7 +252,7 @@ object RedBlackTree { if (ordering.lt(tree.key, from)) return doFrom(tree.right, from) val newLeft = doFrom(tree.left, from) if (newLeft eq tree.left) tree - else if (newLeft eq null) upd(tree.right, tree.key, tree.value, false) + else if (newLeft eq null) upd(tree.right, tree.key, tree.value, overwrite = false) else rebalance(tree, newLeft, tree.right) } private[this] def doTo[A, B](tree: Tree[A, B], to: A)(implicit ordering: Ordering[A]): Tree[A, B] = { @@ -235,7 +260,7 @@ object RedBlackTree { if (ordering.lt(to, tree.key)) return doTo(tree.left, to) val newRight = doTo(tree.right, to) if (newRight eq tree.right) tree - else if (newRight eq null) upd(tree.left, tree.key, tree.value, false) + else if (newRight eq null) upd(tree.left, tree.key, tree.value, overwrite = false) else rebalance(tree, tree.left, newRight) } private[this] def doUntil[A, B](tree: Tree[A, B], until: A)(implicit ordering: Ordering[A]): Tree[A, B] = { @@ -243,18 +268,18 @@ object RedBlackTree { if (ordering.lteq(until, tree.key)) return doUntil(tree.left, until) val newRight = doUntil(tree.right, until) if (newRight eq tree.right) tree - else if (newRight eq null) upd(tree.left, tree.key, tree.value, false) + else if (newRight eq null) upd(tree.left, tree.key, tree.value, overwrite = false) else rebalance(tree, tree.left, newRight) } private[this] def doRange[A, B](tree: Tree[A, B], from: A, until: A)(implicit ordering: Ordering[A]): Tree[A, B] = { if (tree eq null) return null - if (ordering.lt(tree.key, from)) return doRange(tree.right, from, until); - if (ordering.lteq(until, tree.key)) return doRange(tree.left, from, until); + if (ordering.lt(tree.key, from)) return doRange(tree.right, from, until) + if (ordering.lteq(until, tree.key)) return doRange(tree.left, from, until) val newLeft = doFrom(tree.left, from) val newRight = doUntil(tree.right, until) if ((newLeft eq tree.left) && (newRight eq tree.right)) tree - else if (newLeft eq null) upd(newRight, tree.key, tree.value, false); - else if (newRight eq null) upd(newLeft, tree.key, tree.value, false); + else if (newLeft eq null) upd(newRight, tree.key, tree.value, overwrite = false) + else if (newRight eq null) upd(newLeft, tree.key, tree.value, overwrite = false) else rebalance(tree, newLeft, newRight) } @@ -265,7 +290,7 @@ object RedBlackTree { if (n > count) return doDrop(tree.right, n - count - 1) val newLeft = doDrop(tree.left, n) if (newLeft eq tree.left) tree - else if (newLeft eq null) updNth(tree.right, n - count - 1, tree.key, tree.value, false) + else if (newLeft eq null) updNth(tree.right, n - count - 1, tree.key, tree.value, overwrite = false) else rebalance(tree, newLeft, tree.right) } private[this] def doTake[A, B](tree: Tree[A, B], n: Int): Tree[A, B] = { @@ -275,7 +300,7 @@ object RedBlackTree { if (n <= count) return doTake(tree.left, n) val newRight = doTake(tree.right, n - count - 1) if (newRight eq tree.right) tree - else if (newRight eq null) updNth(tree.left, n, tree.key, tree.value, false) + else if (newRight eq null) updNth(tree.left, n, tree.key, tree.value, overwrite = false) else rebalance(tree, tree.left, newRight) } private[this] def doSlice[A, B](tree: Tree[A, B], from: Int, until: Int): Tree[A, B] = { @@ -286,8 +311,8 @@ object RedBlackTree { val newLeft = doDrop(tree.left, from) val newRight = doTake(tree.right, until - count - 1) if ((newLeft eq tree.left) && (newRight eq tree.right)) tree - else if (newLeft eq null) updNth(newRight, from - count - 1, tree.key, tree.value, false) - else if (newRight eq null) updNth(newLeft, until, tree.key, tree.value, false) + else if (newLeft eq null) updNth(newRight, from - count - 1, tree.key, tree.value, overwrite = false) + else if (newRight eq null) updNth(newLeft, until, tree.key, tree.value, overwrite = false) else rebalance(tree, newLeft, newRight) } @@ -300,54 +325,56 @@ object RedBlackTree { // whether the zipper was traversed left-most or right-most. // If the trees were balanced, returns an empty zipper - private[this] def compareDepth[A, B](left: Tree[A, B], right: Tree[A, B]): (List[Tree[A, B]], Boolean, Boolean, Int) = { + private[this] def compareDepth[A, B](left: Tree[A, B], right: Tree[A, B]): (NList[Tree[A, B]], Boolean, Boolean, Int) = { + import NList.cons // Once a side is found to be deeper, unzip it to the bottom - def unzip(zipper: List[Tree[A, B]], leftMost: Boolean): List[Tree[A, B]] = { + def unzip(zipper: NList[Tree[A, B]], leftMost: Boolean): NList[Tree[A, B]] = { val next = if (leftMost) zipper.head.left else zipper.head.right - next match { - case null => zipper - case node => unzip(node :: zipper, leftMost) - } + if (next eq null) zipper + else unzip(cons(next, zipper), leftMost) } // Unzip left tree on the rightmost side and right tree on the leftmost side until one is // found to be deeper, or the bottom is reached def unzipBoth(left: Tree[A, B], right: Tree[A, B], - leftZipper: List[Tree[A, B]], - rightZipper: List[Tree[A, B]], - smallerDepth: Int): (List[Tree[A, B]], Boolean, Boolean, Int) = { + leftZipper: NList[Tree[A, B]], + rightZipper: NList[Tree[A, B]], + smallerDepth: Int): (NList[Tree[A, B]], Boolean, Boolean, Int) = { if (isBlackTree(left) && isBlackTree(right)) { - unzipBoth(left.right, right.left, left :: leftZipper, right :: rightZipper, smallerDepth + 1) + unzipBoth(left.right, right.left, cons(left, leftZipper), cons(right, rightZipper), smallerDepth + 1) } else if (isRedTree(left) && isRedTree(right)) { - unzipBoth(left.right, right.left, left :: leftZipper, right :: rightZipper, smallerDepth) + unzipBoth(left.right, right.left, cons(left, leftZipper), cons(right, rightZipper), smallerDepth) } else if (isRedTree(right)) { - unzipBoth(left, right.left, leftZipper, right :: rightZipper, smallerDepth) + unzipBoth(left, right.left, leftZipper, cons(right, rightZipper), smallerDepth) } else if (isRedTree(left)) { - unzipBoth(left.right, right, left :: leftZipper, rightZipper, smallerDepth) + unzipBoth(left.right, right, cons(left, leftZipper), rightZipper, smallerDepth) } else if ((left eq null) && (right eq null)) { - (Nil, true, false, smallerDepth) + (null, true, false, smallerDepth) } else if ((left eq null) && isBlackTree(right)) { val leftMost = true - (unzip(right :: rightZipper, leftMost), false, leftMost, smallerDepth) + (unzip(cons(right, rightZipper), leftMost), false, leftMost, smallerDepth) } else if (isBlackTree(left) && (right eq null)) { val leftMost = false - (unzip(left :: leftZipper, leftMost), false, leftMost, smallerDepth) + (unzip(cons(left, leftZipper), leftMost), false, leftMost, smallerDepth) } else { sys.error("unmatched trees in unzip: " + left + ", " + right) } } - unzipBoth(left, right, Nil, Nil, 0) + unzipBoth(left, right, null, null, 0) } private[this] def rebalance[A, B](tree: Tree[A, B], newLeft: Tree[A, B], newRight: Tree[A, B]) = { // This is like drop(n-1), but only counting black nodes - def findDepth(zipper: List[Tree[A, B]], depth: Int): List[Tree[A, B]] = zipper match { - case head :: tail if isBlackTree(head) => - if (depth == 1) zipper else findDepth(tail, depth - 1) - case _ :: tail => findDepth(tail, depth) - case Nil => sys.error("Defect: unexpected empty zipper while computing range") - } + @tailrec + def findDepth(zipper: NList[Tree[A, B]], depth: Int): NList[Tree[A, B]] = + if (zipper eq null) { + sys.error("Defect: unexpected empty zipper while computing range") + } else if (isBlackTree(zipper.head)) { + if (depth == 1) zipper else findDepth(zipper.tail, depth - 1) + } else { + findDepth(zipper.tail, depth) + } // Blackening the smaller tree avoids balancing problems on union; // this can't be done later, though, or it would change the result of compareDepth @@ -364,7 +391,7 @@ object RedBlackTree { } else { RedTree(tree.key, tree.value, zipFrom.head, blkNewRight) } - val zippedTree = zipFrom.tail.foldLeft(union: Tree[A, B]) { (tree, node) => + val zippedTree = NList.foldLeft(zipFrom.tail, union: Tree[A, B]) { (tree, node) => if (leftMost) balanceLeft(isBlackTree(node), node.key, node.value, tree, node.right) else @@ -374,6 +401,25 @@ object RedBlackTree { } } + // Null optimized list implementation for tree rebalancing. null presents Nil. + private[this] final class NList[A](val head: A, val tail: NList[A]) + + private[this] final object NList { + + def cons[B](x: B, xs: NList[B]): NList[B] = new NList(x, xs) + + def foldLeft[A, B](xs: NList[A], z: B)(f: (B, A) => B): B = { + var acc = z + var these = xs + while (these ne null) { + acc = f(acc, these.head) + these = these.tail + } + acc + } + + } + /* * Forcing direct fields access using the @inline annotation helps speed up * various operations (especially smallest/greatest and update/delete). @@ -419,32 +465,28 @@ object RedBlackTree { def unapply[A, B](t: BlackTree[A, B]) = Some((t.key, t.value, t.left, t.right)) } - private[this] abstract class TreeIterator[A, B, R](tree: Tree[A, B]) extends Iterator[R] { + private[this] abstract class TreeIterator[A, B, R](root: Tree[A, B], start: Option[A])(implicit ordering: Ordering[A]) extends Iterator[R] { protected[this] def nextResult(tree: Tree[A, B]): R - override def hasNext: Boolean = next ne null + override def hasNext: Boolean = lookahead ne null - override def next: R = next match { + override def next: R = lookahead match { case null => throw new NoSuchElementException("next on empty iterator") case tree => - next = findNext(tree.right) + lookahead = findLeftMostOrPopOnEmpty(goRight(tree)) nextResult(tree) } @tailrec - private[this] def findNext(tree: Tree[A, B]): Tree[A, B] = { - if (tree eq null) popPath() + private[this] def findLeftMostOrPopOnEmpty(tree: Tree[A, B]): Tree[A, B] = + if (tree eq null) popNext() else if (tree.left eq null) tree - else { - pushPath(tree) - findNext(tree.left) - } - } + else findLeftMostOrPopOnEmpty(goLeft(tree)) - private[this] def pushPath(tree: Tree[A, B]) { + private[this] def pushNext(tree: Tree[A, B]) { try { - path(index) = tree + stackOfNexts(index) = tree index += 1 } catch { case _: ArrayIndexOutOfBoundsException => @@ -456,17 +498,17 @@ object RedBlackTree { * An exception handler is used instead of an if-condition to optimize the normal path. * This makes a large difference in iteration speed! */ - assert(index >= path.length) - path :+= null - pushPath(tree) + assert(index >= stackOfNexts.length) + stackOfNexts :+= null + pushNext(tree) } } - private[this] def popPath(): Tree[A, B] = if (index == 0) null else { + private[this] def popNext(): Tree[A, B] = if (index == 0) null else { index -= 1 - path(index) + stackOfNexts(index) } - private[this] var path = if (tree eq null) null else { + private[this] var stackOfNexts = if (root eq null) null else { /* * According to "Ralf Hinze. Constructing red-black trees" [http://www.cs.ox.ac.uk/ralf.hinze/publications/#P5] * the maximum height of a red-black tree is 2*log_2(n + 2) - 2. @@ -475,22 +517,45 @@ object RedBlackTree { * * We also don't store the deepest nodes in the path so the maximum path length is further reduced by one. */ - val maximumHeight = 2 * (32 - Integer.numberOfLeadingZeros(tree.count + 2 - 1)) - 2 - 1 + val maximumHeight = 2 * (32 - Integer.numberOfLeadingZeros(root.count + 2 - 1)) - 2 - 1 new Array[Tree[A, B]](maximumHeight) } private[this] var index = 0 - private[this] var next: Tree[A, B] = findNext(tree) + private[this] var lookahead: Tree[A, B] = start map startFrom getOrElse findLeftMostOrPopOnEmpty(root) + + /** + * Find the leftmost subtree whose key is equal to the given key, or if no such thing, + * the leftmost subtree with the key that would be "next" after it according + * to the ordering. Along the way build up the iterator's path stack so that "next" + * functionality works. + */ + private[this] def startFrom(key: A) : Tree[A,B] = if (root eq null) null else { + @tailrec def find(tree: Tree[A, B]): Tree[A, B] = + if (tree eq null) popNext() + else find( + if (ordering.lteq(key, tree.key)) goLeft(tree) + else goRight(tree) + ) + find(root) + } + + private[this] def goLeft(tree: Tree[A, B]) = { + pushNext(tree) + tree.left + } + + private[this] def goRight(tree: Tree[A, B]) = tree.right } - private[this] class EntriesIterator[A, B](tree: Tree[A, B]) extends TreeIterator[A, B, (A, B)](tree) { + private[this] class EntriesIterator[A: Ordering, B](tree: Tree[A, B], focus: Option[A]) extends TreeIterator[A, B, (A, B)](tree, focus) { override def nextResult(tree: Tree[A, B]) = (tree.key, tree.value) } - private[this] class KeysIterator[A, B](tree: Tree[A, B]) extends TreeIterator[A, B, A](tree) { + private[this] class KeysIterator[A: Ordering, B](tree: Tree[A, B], focus: Option[A]) extends TreeIterator[A, B, A](tree, focus) { override def nextResult(tree: Tree[A, B]) = tree.key } - private[this] class ValuesIterator[A, B](tree: Tree[A, B]) extends TreeIterator[A, B, B](tree) { + private[this] class ValuesIterator[A: Ordering, B](tree: Tree[A, B], focus: Option[A]) extends TreeIterator[A, B, B](tree, focus) { override def nextResult(tree: Tree[A, B]) = tree.value } } diff --git a/src/library/scala/collection/immutable/Seq.scala b/src/library/scala/collection/immutable/Seq.scala index 14610aea33..38855ca6b0 100644 --- a/src/library/scala/collection/immutable/Seq.scala +++ b/src/library/scala/collection/immutable/Seq.scala @@ -8,7 +8,8 @@ -package scala.collection +package scala +package collection package immutable import generic._ diff --git a/src/library/scala/collection/immutable/Set.scala b/src/library/scala/collection/immutable/Set.scala index 8433c2b002..7725ad9ee3 100644 --- a/src/library/scala/collection/immutable/Set.scala +++ b/src/library/scala/collection/immutable/Set.scala @@ -8,7 +8,8 @@ -package scala.collection +package scala +package collection package immutable import generic._ @@ -32,7 +33,10 @@ trait Set[A] extends Iterable[A] with Parallelizable[A, ParSet[A]] { override def companion: GenericCompanion[Set] = Set - override def toSet[B >: A]: Set[B] = this.asInstanceOf[Set[B]] + + + override def toSet[B >: A]: Set[B] = to[({type l[a] = immutable.Set[B]})#l] // for bincompat; remove in dev + override def seq: Set[A] = this protected override def parCombiner = ParSet.newCombiner[A] // if `immutable.SetLike` gets introduced, please move this there! } @@ -44,8 +48,7 @@ trait Set[A] extends Iterable[A] object Set extends ImmutableSetFactory[Set] { /** $setCanBuildFromInfo */ implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, Set[A]] = setCanBuildFrom[A] - override def empty[A]: Set[A] = EmptySet.asInstanceOf[Set[A]] - + /** An optimized representation for immutable empty sets */ private object EmptySet extends AbstractSet[Any] with Set[Any] with Serializable { override def size: Int = 0 @@ -54,7 +57,9 @@ object Set extends ImmutableSetFactory[Set] { def - (elem: Any): Set[Any] = this def iterator: Iterator[Any] = Iterator.empty override def foreach[U](f: Any => U): Unit = {} + override def toSet[B >: Any]: Set[B] = this.asInstanceOf[Set[B]] } + private[collection] def emptyInstance: Set[Any] = EmptySet /** An optimized representation for immutable sets of size 1 */ @SerialVersionUID(1233385750652442003L) @@ -73,6 +78,18 @@ object Set extends ImmutableSetFactory[Set] { override def foreach[U](f: A => U): Unit = { f(elem1) } + override def exists(f: A => Boolean): Boolean = { + f(elem1) + } + override def forall(f: A => Boolean): Boolean = { + f(elem1) + } + override def find(f: A => Boolean): Option[A] = { + if (f(elem1)) Some(elem1) + else None + } + @deprecatedOverriding("Immutable sets should do nothing on toSet but return themselves cast as a Set.", "2.11.0") + override def toSet[B >: A]: Set[B] = this.asInstanceOf[Set[B]] } /** An optimized representation for immutable sets of size 2 */ @@ -93,6 +110,19 @@ object Set extends ImmutableSetFactory[Set] { override def foreach[U](f: A => U): Unit = { f(elem1); f(elem2) } + override def exists(f: A => Boolean): Boolean = { + f(elem1) || f(elem2) + } + override def forall(f: A => Boolean): Boolean = { + f(elem1) && f(elem2) + } + override def find(f: A => Boolean): Option[A] = { + if (f(elem1)) Some(elem1) + else if (f(elem2)) Some(elem2) + else None + } + @deprecatedOverriding("Immutable sets should do nothing on toSet but return themselves cast as a Set.", "2.11.0") + override def toSet[B >: A]: Set[B] = this.asInstanceOf[Set[B]] } /** An optimized representation for immutable sets of size 3 */ @@ -114,6 +144,20 @@ object Set extends ImmutableSetFactory[Set] { override def foreach[U](f: A => U): Unit = { f(elem1); f(elem2); f(elem3) } + override def exists(f: A => Boolean): Boolean = { + f(elem1) || f(elem2) || f(elem3) + } + override def forall(f: A => Boolean): Boolean = { + f(elem1) && f(elem2) && f(elem3) + } + override def find(f: A => Boolean): Option[A] = { + if (f(elem1)) Some(elem1) + else if (f(elem2)) Some(elem2) + else if (f(elem3)) Some(elem3) + else None + } + @deprecatedOverriding("Immutable sets should do nothing on toSet but return themselves cast as a Set.", "2.11.0") + override def toSet[B >: A]: Set[B] = this.asInstanceOf[Set[B]] } /** An optimized representation for immutable sets of size 4 */ @@ -136,6 +180,21 @@ object Set extends ImmutableSetFactory[Set] { override def foreach[U](f: A => U): Unit = { f(elem1); f(elem2); f(elem3); f(elem4) } + override def exists(f: A => Boolean): Boolean = { + f(elem1) || f(elem2) || f(elem3) || f(elem4) + } + override def forall(f: A => Boolean): Boolean = { + f(elem1) && f(elem2) && f(elem3) && f(elem4) + } + override def find(f: A => Boolean): Option[A] = { + if (f(elem1)) Some(elem1) + else if (f(elem2)) Some(elem2) + else if (f(elem3)) Some(elem3) + else if (f(elem4)) Some(elem4) + else None + } + @deprecatedOverriding("Immutable sets should do nothing on toSet but return themselves cast as a Set.", "2.11.0") + override def toSet[B >: A]: Set[B] = this.asInstanceOf[Set[B]] } } diff --git a/src/library/scala/collection/immutable/SetProxy.scala b/src/library/scala/collection/immutable/SetProxy.scala index 06c6843181..d505185e1d 100644 --- a/src/library/scala/collection/immutable/SetProxy.scala +++ b/src/library/scala/collection/immutable/SetProxy.scala @@ -8,7 +8,8 @@ -package scala.collection +package scala +package collection package immutable /** This is a simple wrapper class for <a href="Set.html" @@ -21,6 +22,7 @@ package immutable * * @since 2.8 */ +@deprecated("Proxying is deprecated due to lack of use and compiler-level support.", "2.11.0") trait SetProxy[A] extends Set[A] with SetProxyLike[A, Set[A]] { override def repr = this private def newProxy[B >: A](newSelf: Set[B]): SetProxy[B] = diff --git a/src/library/scala/collection/immutable/SortedMap.scala b/src/library/scala/collection/immutable/SortedMap.scala index eb04231c55..f1493551ab 100644 --- a/src/library/scala/collection/immutable/SortedMap.scala +++ b/src/library/scala/collection/immutable/SortedMap.scala @@ -8,7 +8,8 @@ -package scala.collection +package scala +package collection package immutable import generic._ @@ -82,11 +83,17 @@ self => override def filterKeys(p: A => Boolean): SortedMap[A, B] = new FilteredKeys(p) with SortedMap.Default[A, B] { implicit def ordering: Ordering[A] = self.ordering override def rangeImpl(from : Option[A], until : Option[A]): SortedMap[A, B] = self.rangeImpl(from, until).filterKeys(p) + override def iteratorFrom(start: A) = self iteratorFrom start filter {case (k, _) => p(k)} + override def keysIteratorFrom(start : A) = self keysIteratorFrom start filter p + override def valuesIteratorFrom(start : A) = self iteratorFrom start collect {case (k,v) if p(k) => v} } override def mapValues[C](f: B => C): SortedMap[A, C] = new MappedValues(f) with SortedMap.Default[A, C] { implicit def ordering: Ordering[A] = self.ordering override def rangeImpl(from : Option[A], until : Option[A]): SortedMap[A, C] = self.rangeImpl(from, until).mapValues(f) + override def iteratorFrom(start: A) = self iteratorFrom start map {case (k, v) => (k, f(v))} + override def keysIteratorFrom(start : A) = self keysIteratorFrom start + override def valuesIteratorFrom(start : A) = self valuesIteratorFrom start map f } } @@ -106,13 +113,13 @@ object SortedMap extends ImmutableSortedMapFactory[SortedMap] { val b = SortedMap.newBuilder[A, B1] b ++= this b += ((kv._1, kv._2)) - b.result + b.result() } override def - (key: A): SortedMap[A, B] = { val b = newBuilder for (kv <- this; if kv._1 != key) b += kv - b.result + b.result() } } } diff --git a/src/library/scala/collection/immutable/SortedSet.scala b/src/library/scala/collection/immutable/SortedSet.scala index 3f75d50555..4a8859a7ab 100644 --- a/src/library/scala/collection/immutable/SortedSet.scala +++ b/src/library/scala/collection/immutable/SortedSet.scala @@ -8,7 +8,8 @@ -package scala.collection +package scala +package collection package immutable import generic._ diff --git a/src/library/scala/collection/immutable/Stack.scala b/src/library/scala/collection/immutable/Stack.scala index 357e9a123c..b77b16f23f 100644 --- a/src/library/scala/collection/immutable/Stack.scala +++ b/src/library/scala/collection/immutable/Stack.scala @@ -6,7 +6,8 @@ ** |/ ** \* */ -package scala.collection +package scala +package collection package immutable import generic._ @@ -45,6 +46,7 @@ object Stack extends SeqFactory[Stack] { * @define willNotTerminateInf */ @SerialVersionUID(1976480595012942526L) +@deprecated("Stack is an inelegant and potentially poorly-performing wrapper around List. Use List instead: stack push x becomes x :: list; stack.pop is list.tail.", "2.11.0") class Stack[+A] protected (protected val elems: List[A]) extends AbstractSeq[A] with LinearSeq[A] diff --git a/src/library/scala/collection/immutable/Stream.scala b/src/library/scala/collection/immutable/Stream.scala index 5bb4ef5f21..60de147477 100644 --- a/src/library/scala/collection/immutable/Stream.scala +++ b/src/library/scala/collection/immutable/Stream.scala @@ -6,7 +6,8 @@ ** |/ ** \* */ -package scala.collection +package scala +package collection package immutable import generic._ @@ -181,11 +182,14 @@ import scala.language.implicitConversions * @define coll stream * @define orderDependent * @define orderDependentFold + * @define willTerminateInf Note: lazily evaluated; will terminate for infinite-sized collections. */ +@deprecatedInheritance("This class will be sealed.", "2.11.0") abstract class Stream[+A] extends AbstractSeq[A] with LinearSeq[A] with GenericTraversableTemplate[A, Stream] - with LinearSeqOptimized[A, Stream[A]] { + with LinearSeqOptimized[A, Stream[A]] + with Serializable { self => override def companion: GenericCompanion[Stream] = Stream @@ -286,9 +290,8 @@ self => len } - /** It's an imperfect world, but at least we can bottle up the - * imperfection in a capsule. - */ + // It's an imperfect world, but at least we can bottle up the + // imperfection in a capsule. @inline private def asThat[That](x: AnyRef): That = x.asInstanceOf[That] @inline private def asStream[B](x: AnyRef): Stream[B] = x.asInstanceOf[Stream[B]] @inline private def isStreamBuilder[B, That](bf: CanBuildFrom[Stream[A], B, That]) = @@ -385,12 +388,17 @@ self => // 1) stackoverflows (could be achieved with tailrec, too) // 2) out of memory errors for big streams (`this` reference can be eliminated from the stack) var rest: Stream[A] = this - while (rest.nonEmpty && !pf.isDefinedAt(rest.head)) rest = rest.tail + + // Avoids calling both `pf.isDefined` and `pf.apply`. + var newHead: B = null.asInstanceOf[B] + val runWith = pf.runWith((b: B) => newHead = b) + + while (rest.nonEmpty && !runWith(rest.head)) rest = rest.tail // without the call to the companion object, a thunk is created for the tail of the new stream, // and the closure of the thunk will reference `this` if (rest.isEmpty) Stream.Empty.asInstanceOf[That] - else Stream.collectedTail(rest, pf, bf).asInstanceOf[That] + else Stream.collectedTail(newHead, rest, pf, bf).asInstanceOf[That] } } @@ -725,10 +733,15 @@ self => * // produces: "5, 6, 7, 8, 9" * }}} */ - override def take(n: Int): Stream[A] = + override def take(n: Int): Stream[A] = ( + // Note that the n == 1 condition appears redundant but is not. + // It prevents "tail" from being referenced (and its head being evaluated) + // when obtaining the last element of the result. Such are the challenges + // of working with a lazy-but-not-really sequence. if (n <= 0 || isEmpty) Stream.empty else if (n == 1) cons(head, Stream.empty) else cons(head, tail take n-1) + ) @tailrec final override def drop(n: Int): Stream[A] = if (n <= 0 || isEmpty) this @@ -784,8 +797,23 @@ self => these } - // there's nothing we can do about dropRight, so we just keep the definition - // in LinearSeq + /** + * @inheritdoc + * $willTerminateInf + */ + override def dropRight(n: Int): Stream[A] = { + // We make dropRight work for possibly infinite streams by carrying + // a buffer of the dropped size. As long as the buffer is full and the + // rest is non-empty, we can feed elements off the buffer head. When + // the rest becomes empty, the full buffer is the dropped elements. + def advance(stub0: List[A], stub1: List[A], rest: Stream[A]): Stream[A] = { + if (rest.isEmpty) Stream.empty + else if (stub0.isEmpty) advance(stub1.reverse, Nil, rest) + else cons(stub0.head, advance(stub0.tail, rest.head :: stub1, rest.tail)) + } + if (n <= 0) this + else advance((this take n).toList, Nil, this drop n) + } /** Returns the longest prefix of this `Stream` whose elements satisfy the * predicate `p`. @@ -927,19 +955,21 @@ self => * `Stream`. * @example {{{ * val sov: Stream[Vector[Int]] = Vector(0) #:: Vector(0, 0) #:: sov.zip(sov.tail).map { n => n._1 ++ n._2 } - * sov flatten take 10 mkString ", " + * sov.flatten take 10 mkString ", " * // produces: "0, 0, 0, 0, 0, 0, 0, 0, 0, 0" * }}} */ override def flatten[B](implicit asTraversable: A => /*<:<!!!*/ GenTraversableOnce[B]): Stream[B] = { - def flatten1(t: Traversable[B]): Stream[B] = - if (!t.isEmpty) - cons(t.head, flatten1(t.tail)) - else - tail.flatten - - if (isEmpty) Stream.empty - else flatten1(asTraversable(head).seq.toTraversable) + var st: Stream[A] = this + while (st.nonEmpty) { + val h = asTraversable(st.head) + if (h.isEmpty) { + st = st.tail + } else { + return h.toStream #::: st.tail.flatten + } + } + Stream.empty } override def view = new StreamView[A, Stream[A]] { @@ -973,7 +1003,7 @@ final class StreamIterator[+A] private() extends AbstractIterator[A] with Iterat def hasNext: Boolean = these.v.nonEmpty def next(): A = - if (isEmpty) Iterator.empty.next + if (isEmpty) Iterator.empty.next() else { val cur = these.v val result = cur.head @@ -1023,7 +1053,7 @@ object Stream extends SeqFactory[Stream] { def result: Stream[A] = parts.toStream flatMap (_.toStream) } - object Empty extends Stream[Nothing] with Serializable { + object Empty extends Stream[Nothing] { override def isEmpty = true override def head = throw new NoSuchElementException("head of empty stream") override def tail = throw new UnsupportedOperationException("tail of empty stream") @@ -1074,15 +1104,19 @@ object Stream extends SeqFactory[Stream] { /** A lazy cons cell, from which streams are built. */ @SerialVersionUID(-602202424901551803L) - final class Cons[+A](hd: A, tl: => Stream[A]) extends Stream[A] with Serializable { + final class Cons[+A](hd: A, tl: => Stream[A]) extends Stream[A] { override def isEmpty = false override def head = hd @volatile private[this] var tlVal: Stream[A] = _ - def tailDefined: Boolean = tlVal ne null + @volatile private[this] var tlGen = tl _ + def tailDefined: Boolean = tlGen eq null override def tail: Stream[A] = { if (!tailDefined) synchronized { - if (!tailDefined) tlVal = tl + if (!tailDefined) { + tlVal = tlGen() + tlGen = null + } } tlVal @@ -1149,8 +1183,8 @@ object Stream extends SeqFactory[Stream] { cons(stream.head, stream.tail filter p) } - private[immutable] def collectedTail[A, B, That](stream: Stream[A], pf: PartialFunction[A, B], bf: CanBuildFrom[Stream[A], B, That]) = { - cons(pf(stream.head), stream.tail.collect(pf)(bf).asInstanceOf[Stream[B]]) + private[immutable] def collectedTail[A, B, That](head: B, stream: Stream[A], pf: PartialFunction[A, B], bf: CanBuildFrom[Stream[A], B, That]) = { + cons(head, stream.tail.collect(pf)(bf).asInstanceOf[Stream[B]]) } } diff --git a/src/library/scala/collection/immutable/StreamView.scala b/src/library/scala/collection/immutable/StreamView.scala index 5a24b77eb3..127ed76eb5 100644 --- a/src/library/scala/collection/immutable/StreamView.scala +++ b/src/library/scala/collection/immutable/StreamView.scala @@ -1,4 +1,5 @@ -package scala.collection +package scala +package collection package immutable trait StreamView[+A, +Coll] extends StreamViewLike[A, Coll, StreamView[A, Coll]] { } diff --git a/src/library/scala/collection/immutable/StreamViewLike.scala b/src/library/scala/collection/immutable/StreamViewLike.scala index 236308da2e..c2eb85815d 100644 --- a/src/library/scala/collection/immutable/StreamViewLike.scala +++ b/src/library/scala/collection/immutable/StreamViewLike.scala @@ -1,4 +1,5 @@ -package scala.collection +package scala +package collection package immutable import generic._ @@ -70,9 +71,3 @@ extends SeqView[A, Coll] override def stringPrefix = "StreamView" } - - - - - - diff --git a/src/library/scala/collection/immutable/StringLike.scala b/src/library/scala/collection/immutable/StringLike.scala index edea89b555..8e1d950d00 100644 --- a/src/library/scala/collection/immutable/StringLike.scala +++ b/src/library/scala/collection/immutable/StringLike.scala @@ -6,10 +6,10 @@ ** |/ ** \* */ -package scala.collection +package scala +package collection package immutable -import generic._ import mutable.Builder import scala.util.matching.Regex import scala.math.ScalaNumber @@ -19,12 +19,11 @@ import scala.reflect.ClassTag * @since 2.8 */ object StringLike { - // just statics for companion class. - private final val LF: Char = 0x0A - private final val FF: Char = 0x0C - private final val CR: Char = 0x0D - private final val SU: Char = 0x1A + private final val LF = 0x0A + private final val FF = 0x0C + private final val CR = 0x0D + private final val SU = 0x1A } import StringLike._ @@ -60,8 +59,8 @@ self => val start = from max 0 val end = until min length - if (start >= end) newBuilder.result - else (newBuilder ++= toString.substring(start, end)).result + if (start >= end) newBuilder.result() + else (newBuilder ++= toString.substring(start, end)).result() } /** Return the current string concatenated `n` times. @@ -132,6 +131,7 @@ self => * end characters, i.e. apply `.stripLineEnd` to all lines * returned by `linesWithSeparators`. */ + @deprecated("Use `lines` instead.","2.11.0") def linesIterator: Iterator[String] = linesWithSeparators map (line => new WrappedString(line).stripLineEnd) @@ -165,8 +165,8 @@ self => * @return the resulting string */ def replaceAllLiterally(literal: String, replacement: String): String = { - val arg1 = java.util.regex.Pattern.quote(literal) - val arg2 = java.util.regex.Matcher.quoteReplacement(replacement) + val arg1 = Regex.quote(literal) + val arg2 = Regex.quoteReplacement(replacement) toString.replaceAll(arg1, arg2) } @@ -223,12 +223,33 @@ self => */ def r(groupNames: String*): Regex = new Regex(toString, groupNames: _*) + /** + * @throws `java.lang.IllegalArgumentException` - If the string does not contain a parsable boolean. + */ def toBoolean: Boolean = parseBoolean(toString) + /** + * @throws `java.lang.NumberFormatException` - If the string does not contain a parsable byte. + */ def toByte: Byte = java.lang.Byte.parseByte(toString) + /** + * @throws `java.lang.NumberFormatException` - If the string does not contain a parsable short. + */ def toShort: Short = java.lang.Short.parseShort(toString) + /** + * @throws `java.lang.NumberFormatException` - If the string does not contain a parsable int. + */ def toInt: Int = java.lang.Integer.parseInt(toString) + /** + * @throws `java.lang.NumberFormatException` - If the string does not contain a parsable long. + */ def toLong: Long = java.lang.Long.parseLong(toString) + /** + * @throws `java.lang.NumberFormatException` - If the string does not contain a parsable float. + */ def toFloat: Float = java.lang.Float.parseFloat(toString) + /** + * @throws `java.lang.NumberFormatException` - If the string does not contain a parsable double. + */ def toDouble: Double = java.lang.Double.parseDouble(toString) private def parseBoolean(s: String): Boolean = diff --git a/src/library/scala/collection/immutable/StringOps.scala b/src/library/scala/collection/immutable/StringOps.scala index a650d98697..6737692fb1 100644 --- a/src/library/scala/collection/immutable/StringOps.scala +++ b/src/library/scala/collection/immutable/StringOps.scala @@ -6,9 +6,8 @@ ** |/ ** \* */ - - -package scala.collection +package scala +package collection package immutable import mutable.StringBuilder diff --git a/src/library/scala/collection/immutable/Traversable.scala b/src/library/scala/collection/immutable/Traversable.scala index 5188343011..775d635fae 100644 --- a/src/library/scala/collection/immutable/Traversable.scala +++ b/src/library/scala/collection/immutable/Traversable.scala @@ -8,7 +8,8 @@ -package scala.collection +package scala +package collection package immutable import generic._ diff --git a/src/library/scala/collection/immutable/TreeMap.scala b/src/library/scala/collection/immutable/TreeMap.scala index 5b4db2686a..8cc99a53e6 100644 --- a/src/library/scala/collection/immutable/TreeMap.scala +++ b/src/library/scala/collection/immutable/TreeMap.scala @@ -6,9 +6,8 @@ ** |/ ** \* */ - - -package scala.collection +package scala +package collection package immutable import generic._ @@ -45,15 +44,13 @@ object TreeMap extends ImmutableSortedMapFactory[TreeMap] { * @define mayNotTerminateInf * @define willNotTerminateInf */ +@deprecatedInheritance("The implementation details of immutable tree maps make inheriting from them unwise.", "2.11.0") class TreeMap[A, +B] private (tree: RB.Tree[A, B])(implicit val ordering: Ordering[A]) extends SortedMap[A, B] with SortedMapLike[A, B, TreeMap[A, B]] with MapLike[A, B, TreeMap[A, B]] with Serializable { - @deprecated("use `ordering.lt` instead", "2.10.0") - def isSmaller(x: A, y: A) = ordering.lt(x, y) - override protected[this] def newBuilder : Builder[(A, B), TreeMap[A, B]] = TreeMap.newBuilder[A, B] @@ -111,7 +108,7 @@ class TreeMap[A, +B] private (tree: RB.Tree[A, B])(implicit val ordering: Orderi private[this] def countWhile(p: ((A, B)) => Boolean): Int = { var result = 0 val it = iterator - while (it.hasNext && p(it.next)) result += 1 + while (it.hasNext && p(it.next())) result += 1 result } override def dropWhile(p: ((A, B)) => Boolean) = drop(countWhile(p)) @@ -131,7 +128,7 @@ class TreeMap[A, +B] private (tree: RB.Tree[A, B])(implicit val ordering: Orderi * @param value the value to be associated with `key` * @return a new $coll with the updated binding */ - override def updated [B1 >: B](key: A, value: B1): TreeMap[A, B1] = new TreeMap(RB.update(tree, key, value, true)) + override def updated [B1 >: B](key: A, value: B1): TreeMap[A, B1] = new TreeMap(RB.update(tree, key, value, overwrite = true)) /** Add a key/value pair to this map. * @tparam B1 type of the value of the new binding, a supertype of `B` @@ -171,7 +168,7 @@ class TreeMap[A, +B] private (tree: RB.Tree[A, B])(implicit val ordering: Orderi */ def insert [B1 >: B](key: A, value: B1): TreeMap[A, B1] = { assert(!RB.contains(tree, key)) - new TreeMap(RB.update(tree, key, value, true)) + new TreeMap(RB.update(tree, key, value, overwrite = true)) } def - (key:A): TreeMap[A, B] = @@ -192,16 +189,16 @@ class TreeMap[A, +B] private (tree: RB.Tree[A, B])(implicit val ordering: Orderi * @return the new iterator */ override def iterator: Iterator[(A, B)] = RB.iterator(tree) + override def iteratorFrom(start: A): Iterator[(A, B)] = RB.iterator(tree, Some(start)) override def keysIterator: Iterator[A] = RB.keysIterator(tree) + override def keysIteratorFrom(start: A): Iterator[A] = RB.keysIterator(tree, Some(start)) + override def valuesIterator: Iterator[B] = RB.valuesIterator(tree) + override def valuesIteratorFrom(start: A): Iterator[B] = RB.valuesIterator(tree, Some(start)) override def contains(key: A): Boolean = RB.contains(tree, key) override def isDefinedAt(key: A): Boolean = RB.contains(tree, key) override def foreach[U](f : ((A,B)) => U) = RB.foreach(tree, f) } - - - - diff --git a/src/library/scala/collection/immutable/TreeSet.scala b/src/library/scala/collection/immutable/TreeSet.scala index 494776587d..681dbbd1a8 100644 --- a/src/library/scala/collection/immutable/TreeSet.scala +++ b/src/library/scala/collection/immutable/TreeSet.scala @@ -8,7 +8,8 @@ -package scala.collection +package scala +package collection package immutable import generic._ @@ -48,9 +49,13 @@ object TreeSet extends ImmutableSortedSetFactory[TreeSet] { * @define willNotTerminateInf */ @SerialVersionUID(-5685982407650748405L) +@deprecatedInheritance("The implementation details of immutable tree sets make inheriting from them unwise.", "2.11.0") class TreeSet[A] private (tree: RB.Tree[A, Unit])(implicit val ordering: Ordering[A]) extends SortedSet[A] with SortedSetLike[A, TreeSet[A]] with Serializable { + if (ordering eq null) + throw new NullPointerException("ordering must not be null") + override def stringPrefix = "TreeSet" override def size = RB.count(tree) @@ -89,16 +94,13 @@ class TreeSet[A] private (tree: RB.Tree[A, Unit])(implicit val ordering: Orderin private[this] def countWhile(p: A => Boolean): Int = { var result = 0 val it = iterator - while (it.hasNext && p(it.next)) result += 1 + while (it.hasNext && p(it.next())) result += 1 result } override def dropWhile(p: A => Boolean) = drop(countWhile(p)) override def takeWhile(p: A => Boolean) = take(countWhile(p)) override def span(p: A => Boolean) = splitAt(countWhile(p)) - @deprecated("use `ordering.lt` instead", "2.10.0") - def isSmaller(x: A, y: A) = compare(x,y) < 0 - def this()(implicit ordering: Ordering[A]) = this(null)(ordering) private def newSet(t: RB.Tree[A, Unit]) = new TreeSet[A](t) @@ -112,7 +114,7 @@ class TreeSet[A] private (tree: RB.Tree[A, Unit])(implicit val ordering: Orderin * @param elem a new element to add. * @return a new $coll containing `elem` and all the elements of this $coll. */ - def + (elem: A): TreeSet[A] = newSet(RB.update(tree, elem, (), false)) + def + (elem: A): TreeSet[A] = newSet(RB.update(tree, elem, (), overwrite = false)) /** A new `TreeSet` with the entry added is returned, * assuming that elem is <em>not</em> in the TreeSet. @@ -122,7 +124,7 @@ class TreeSet[A] private (tree: RB.Tree[A, Unit])(implicit val ordering: Orderin */ def insert(elem: A): TreeSet[A] = { assert(!RB.contains(tree, elem)) - newSet(RB.update(tree, elem, (), false)) + newSet(RB.update(tree, elem, (), overwrite = false)) } /** Creates a new `TreeSet` with the entry removed. @@ -147,6 +149,7 @@ class TreeSet[A] private (tree: RB.Tree[A, Unit])(implicit val ordering: Orderin * @return the new iterator */ def iterator: Iterator[A] = RB.keysIterator(tree) + override def keysIteratorFrom(start: A): Iterator[A] = RB.keysIterator(tree, Some(start)) override def foreach[U](f: A => U) = RB.foreachKey(tree, f) diff --git a/src/library/scala/collection/immutable/TrieIterator.scala b/src/library/scala/collection/immutable/TrieIterator.scala index b0bd253359..d7335e80f1 100644 --- a/src/library/scala/collection/immutable/TrieIterator.scala +++ b/src/library/scala/collection/immutable/TrieIterator.scala @@ -6,7 +6,8 @@ ** |/ ** \* */ -package scala.collection +package scala +package collection package immutable import HashMap.{ HashTrieMap, HashMapCollision1, HashMap1 } @@ -94,7 +95,7 @@ private[collection] abstract class TrieIterator[+T](elems: Array[Iterable[T]]) e def hasNext = (subIter ne null) || depth >= 0 def next(): T = { if (subIter ne null) { - val el = subIter.next + val el = subIter.next() if (!subIter.hasNext) subIter = null el @@ -135,7 +136,7 @@ private[collection] abstract class TrieIterator[+T](elems: Array[Iterable[T]]) e } else { subIter = m.iterator - next + next() } // The much slower version: // @@ -177,7 +178,6 @@ private[collection] abstract class TrieIterator[+T](elems: Array[Iterable[T]]) e if (depth > 0) { // 2) topmost comes before (is not) arrayD // steal a portion of top to create a new iterator - val topmost = arrayStack(0) if (posStack(0) == arrayStack(0).length - 1) { // 2a) only a single entry left on top // this means we have to modify this iterator - pop topmost diff --git a/src/library/scala/collection/immutable/Vector.scala b/src/library/scala/collection/immutable/Vector.scala index bcce4a99bd..c7da447f72 100644 --- a/src/library/scala/collection/immutable/Vector.scala +++ b/src/library/scala/collection/immutable/Vector.scala @@ -18,21 +18,16 @@ import scala.collection.parallel.immutable.ParVector /** Companion object to the Vector class */ -object Vector extends SeqFactory[Vector] { - // left lying around for binary compatibility check - private[collection] class VectorReusableCBF extends GenericCanBuildFrom[Nothing] { - override def apply() = newBuilder[Nothing] - } - // left lying around for binary compatibility check - private val VectorReusableCBF: GenericCanBuildFrom[Nothing] = new VectorReusableCBF - - override lazy val ReusableCBF = - scala.collection.IndexedSeq.ReusableCBF.asInstanceOf[GenericCanBuildFrom[Nothing]] +object Vector extends IndexedSeqFactory[Vector] { def newBuilder[A]: Builder[A, Vector[A]] = new VectorBuilder[A] implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, Vector[A]] = ReusableCBF.asInstanceOf[GenericCanBuildFrom[A]] private[immutable] val NIL = new Vector[Nothing](0, 0, 0) override def empty[A]: Vector[A] = NIL + + // Constants governing concat strategy for performance + private final val Log2ConcatFaster = 5 + private final val TinyAppendFaster = 2 } // in principle, most members should be private. however, access privileges must @@ -64,7 +59,7 @@ object Vector extends SeqFactory[Vector] { * @define mayNotTerminateInf * @define willNotTerminateInf */ -final class Vector[+A](private[collection] val startIndex: Int, private[collection] val endIndex: Int, focus: Int) +final class Vector[+A] private[immutable] (private[collection] val startIndex: Int, private[collection] val endIndex: Int, focus: Int) extends AbstractSeq[A] with IndexedSeq[A] with GenericTraversableTemplate[A, Vector] @@ -113,7 +108,7 @@ override def companion: GenericCompanion[Vector] = Vector if (0 < i) { i -= 1 self(i) - } else Iterator.empty.next + } else Iterator.empty.next() } // TODO: reverse @@ -148,7 +143,7 @@ override def companion: GenericCompanion[Vector] = Vector if (bf eq IndexedSeq.ReusableCBF) appendFront(elem).asInstanceOf[That] // just ignore bf else super.+:(elem)(bf) - override def :+[B >: A, That](elem: B)(implicit bf: CanBuildFrom[Vector[A], B, That]): That = + override def :+[B >: A, That](elem: B)(implicit bf: CanBuildFrom[Vector[A], B, That]): That = if (bf eq IndexedSeq.ReusableCBF) appendBack(elem).asInstanceOf[That] // just ignore bf else super.:+(elem)(bf) @@ -214,10 +209,29 @@ override def companion: GenericCompanion[Vector] = Vector override /*IterableLike*/ def splitAt(n: Int): (Vector[A], Vector[A]) = (take(n), drop(n)) - // concat (stub) - + // concat (suboptimal but avoids worst performance gotchas) override def ++[B >: A, That](that: GenTraversableOnce[B])(implicit bf: CanBuildFrom[Vector[A], B, That]): That = { - super.++(that.seq) + if (bf eq IndexedSeq.ReusableCBF) { + import Vector.{Log2ConcatFaster, TinyAppendFaster} + if (that.isEmpty) this.asInstanceOf[That] + else { + val again = if (!that.isTraversableAgain) that.toVector else that + again.size match { + // Often it's better to append small numbers of elements (or prepend if RHS is a vector) + case n if n <= TinyAppendFaster || n < (this.size >> Log2ConcatFaster) => + var v: Vector[B] = this + for (x <- again) v = v :+ x + v.asInstanceOf[That] + case n if this.size < (n >> Log2ConcatFaster) && again.isInstanceOf[Vector[_]] => + var v = again.asInstanceOf[Vector[B]] + val ri = this.reverseIterator + while (ri.hasNext) v = ri.next +: v + v.asInstanceOf[That] + case _ => super.++(again) + } + } + } + else super.++(that.seq) } @@ -251,8 +265,8 @@ override def companion: GenericCompanion[Vector] = Vector private[immutable] def appendFront[B>:A](value: B): Vector[B] = { if (endIndex != startIndex) { - var blockIndex = (startIndex - 1) & ~31 - var lo = (startIndex - 1) & 31 + val blockIndex = (startIndex - 1) & ~31 + val lo = (startIndex - 1) & 31 if (startIndex != blockIndex + 32) { val s = new Vector(startIndex - 1, endIndex, blockIndex) @@ -270,7 +284,7 @@ override def companion: GenericCompanion[Vector] = Vector //println("----- appendFront " + value + " at " + (startIndex - 1) + " reached block start") if (shift != 0) { // case A: we can shift right on the top level - debug + debug() //println("shifting right by " + shiftBlocks + " at level " + (depth-1) + " (had "+freeSpace+" free space)") if (depth > 1) { @@ -280,7 +294,7 @@ override def companion: GenericCompanion[Vector] = Vector s.initFrom(this) s.dirty = dirty s.shiftTopLevel(0, shiftBlocks) // shift right by n blocks - s.debug + s.debug() s.gotoFreshPosWritable(newFocus, newBlockIndex, newFocus ^ newBlockIndex) // maybe create pos; prepare for writing s.display0(lo) = value.asInstanceOf[AnyRef] //assert(depth == s.depth) @@ -298,7 +312,7 @@ override def companion: GenericCompanion[Vector] = Vector s.shiftTopLevel(0, shiftBlocks) // shift right by n elements s.gotoPosWritable(newFocus, newBlockIndex, newFocus ^ newBlockIndex) // prepare for writing s.display0(shift-1) = value.asInstanceOf[AnyRef] - s.debug + s.debug() s } } else if (blockIndex < 0) { @@ -313,10 +327,10 @@ override def companion: GenericCompanion[Vector] = Vector val s = new Vector(startIndex - 1 + move, endIndex + move, newBlockIndex) s.initFrom(this) s.dirty = dirty - s.debug + s.debug() s.gotoFreshPosWritable(newFocus, newBlockIndex, newFocus ^ newBlockIndex) // could optimize: we know it will create a whole branch s.display0(lo) = value.asInstanceOf[AnyRef] - s.debug + s.debug() //assert(s.depth == depth+1) s } else { @@ -348,8 +362,8 @@ override def companion: GenericCompanion[Vector] = Vector // //println("------- append " + value) // debug() if (endIndex != startIndex) { - var blockIndex = endIndex & ~31 - var lo = endIndex & 31 + val blockIndex = endIndex & ~31 + val lo = endIndex & 31 if (endIndex != blockIndex) { //println("will make writable block (from "+focus+") at: " + blockIndex) @@ -366,7 +380,7 @@ override def companion: GenericCompanion[Vector] = Vector //println("----- appendBack " + value + " at " + endIndex + " reached block end") if (shift != 0) { - debug + debug() //println("shifting left by " + shiftBlocks + " at level " + (depth-1) + " (had "+startIndex+" free space)") if (depth > 1) { val newBlockIndex = blockIndex - shift @@ -375,10 +389,10 @@ override def companion: GenericCompanion[Vector] = Vector s.initFrom(this) s.dirty = dirty s.shiftTopLevel(shiftBlocks, 0) // shift left by n blocks - s.debug + s.debug() s.gotoFreshPosWritable(newFocus, newBlockIndex, newFocus ^ newBlockIndex) s.display0(lo) = value.asInstanceOf[AnyRef] - s.debug + s.debug() //assert(depth == s.depth) s } else { @@ -394,7 +408,7 @@ override def companion: GenericCompanion[Vector] = Vector s.shiftTopLevel(shiftBlocks, 0) // shift right by n elements s.gotoPosWritable(newFocus, newBlockIndex, newFocus ^ newBlockIndex) s.display0(32 - shift) = value.asInstanceOf[AnyRef] - s.debug + s.debug() s } } else { @@ -409,7 +423,7 @@ override def companion: GenericCompanion[Vector] = Vector //assert(s.depth == depth+1) might or might not create new level! if (s.depth == depth+1) { //println("creating new level " + s.depth + " (had "+0+" free space)") - s.debug + s.debug() } s } @@ -583,9 +597,7 @@ override def companion: GenericCompanion[Vector] = Vector } private def dropFront0(cutIndex: Int): Vector[A] = { - var blockIndex = cutIndex & ~31 - var lo = cutIndex & 31 - + val blockIndex = cutIndex & ~31 val xor = cutIndex ^ (endIndex - 1) val d = requiredDepth(xor) val shift = (cutIndex & ~((1 << (5*d))-1)) @@ -615,9 +627,7 @@ override def companion: GenericCompanion[Vector] = Vector } private def dropBack0(cutIndex: Int): Vector[A] = { - var blockIndex = (cutIndex - 1) & ~31 - var lo = ((cutIndex - 1) & 31) + 1 - + val blockIndex = (cutIndex - 1) & ~31 val xor = startIndex ^ (cutIndex - 1) val d = requiredDepth(xor) val shift = (startIndex & ~((1 << (5*d))-1)) @@ -639,14 +649,13 @@ override def companion: GenericCompanion[Vector] = Vector } -class VectorIterator[+A](_startIndex: Int, _endIndex: Int) +class VectorIterator[+A](_startIndex: Int, endIndex: Int) extends AbstractIterator[A] with Iterator[A] with VectorPointer[A @uncheckedVariance] { private var blockIndex: Int = _startIndex & ~31 private var lo: Int = _startIndex & 31 - private var endIndex: Int = _endIndex private var endLo = math.min(endIndex - blockIndex, 32) @@ -676,13 +685,13 @@ extends AbstractIterator[A] res } - private[collection] def remainingElementCount: Int = (_endIndex - (blockIndex + lo)) max 0 + private[collection] def remainingElementCount: Int = (endIndex - (blockIndex + lo)) max 0 /** Creates a new vector which consists of elements remaining in this iterator. * Such a vector can then be split into several vectors using methods like `take` and `drop`. */ private[collection] def remainingVector: Vector[A] = { - val v = new Vector(blockIndex + lo, _endIndex, blockIndex + lo) + val v = new Vector(blockIndex + lo, endIndex, blockIndex + lo) v.initFrom(this) v } diff --git a/src/library/scala/collection/immutable/WrappedString.scala b/src/library/scala/collection/immutable/WrappedString.scala index edcab31f33..7592316650 100644 --- a/src/library/scala/collection/immutable/WrappedString.scala +++ b/src/library/scala/collection/immutable/WrappedString.scala @@ -8,7 +8,8 @@ -package scala.collection +package scala +package collection package immutable import generic._ @@ -28,6 +29,7 @@ import mutable.{Builder, StringBuilder} * @define Coll `WrappedString` * @define coll wrapped string */ +@deprecatedInheritance("Inherit from StringLike instead of WrappedString.", "2.11.0") class WrappedString(val self: String) extends AbstractSeq[Char] with IndexedSeq[Char] with StringLike[WrappedString] { override protected[this] def thisCollection: WrappedString = this diff --git a/src/library/scala/collection/immutable/package.scala b/src/library/scala/collection/immutable/package.scala deleted file mode 100644 index ed0c1b3736..0000000000 --- a/src/library/scala/collection/immutable/package.scala +++ /dev/null @@ -1,93 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala.collection - -package immutable { - /** It looks like once upon a time this was used by ParRange, but - * since December 2010 in r23721 it is not used by anything. We - * should not have public API traits with seductive names like - * "RangeUtils" which are neither documented nor used. - */ - @deprecated("this class will be removed", "2.10.0") - trait RangeUtils[+Repr <: RangeUtils[Repr]] { - def start: Int - def end: Int - def step: Int - def inclusive: Boolean - def create(_start: Int, _end: Int, _step: Int, _inclusive: Boolean): Repr - - private final def inclusiveLast: Int = { - val size = end.toLong - start.toLong - (size / step.toLong * step.toLong + start.toLong).toInt - } - - final def _last: Int = ( - if (!inclusive) { - if (step == 1 || step == -1) end - step - else { - val inclast = inclusiveLast - if ((end.toLong - start.toLong) % step == 0) inclast - step else inclast - } - } - else if (step == 1 || step == -1) end - else inclusiveLast - ) - - final def _foreach[U](f: Int => U) = if (_length > 0) { - var i = start - val last = _last - while (i != last) { - f(i) - i += step - } - } - - final def _length: Int = ( - if (!inclusive) { - if (end > start == step > 0 && start != end) { - (_last.toLong - start.toLong) / step.toLong + 1 - } else 0 - }.toInt - else { - if (end > start == step > 0 || start == end) { - (_last.toLong - start.toLong) / step.toLong + 1 - } else 0 - }.toInt - ) - - final def _apply(idx: Int): Int = { - if (idx < 0 || idx >= _length) throw new IndexOutOfBoundsException(idx.toString) - start + idx * step - } - - private def locationAfterN(n: Int) = ( - if (n > 0) { - if (step > 0) - scala.math.min(start.toLong + step.toLong * n.toLong, _last.toLong).toInt - else - scala.math.max(start.toLong + step.toLong * n.toLong, _last.toLong).toInt - } - else start - ) - - final def _take(n: Int) = ( - if (n > 0 && _length > 0) - create(start, locationAfterN(n), step, true) - else - create(start, start, step, false) - ) - - final def _drop(n: Int) = create(locationAfterN(n), end, step, inclusive) - final def _slice(from: Int, until: Int) = _drop(from)._take(until - from) - } -} - -package object immutable { - /** Nothing left after I promoted RangeUtils to the package. */ -} diff --git a/src/library/scala/collection/mutable/AVLTree.scala b/src/library/scala/collection/mutable/AVLTree.scala index 157e5dae62..cc2acb74d4 100644 --- a/src/library/scala/collection/mutable/AVLTree.scala +++ b/src/library/scala/collection/mutable/AVLTree.scala @@ -10,13 +10,12 @@ package scala package collection package mutable - /** - * An immutable AVL Tree implementation used by mutable.TreeSet + * An immutable AVL Tree implementation formerly used by mutable.TreeSet * * @author Lucien Pereira - * */ +@deprecated("AVLTree and its related classes are being removed from the standard library since they're not different enough from RedBlackTree to justify keeping them.", "2.11.2") private[mutable] sealed trait AVLTree[+A] extends Serializable { def balance: Int @@ -65,13 +64,19 @@ private[mutable] sealed trait AVLTree[+A] extends Serializable { def doubleRightRotation[B >: A]: Node[B] = sys.error("Should not happen.") } +/** + * @deprecated("AVLTree and its related classes are being removed from the standard library since they're not different enough from RedBlackTree to justify keeping them.", "2.11.0") + */ private case object Leaf extends AVLTree[Nothing] { override val balance: Int = 0 override val depth: Int = -1 } -private case class Node[A](val data: A, val left: AVLTree[A], val right: AVLTree[A]) extends AVLTree[A] { +/** + * @deprecated("AVLTree and its related classes are being removed from the standard library since they're not different enough from RedBlackTree to justify keeping them.", "2.11.0") + */ +private case class Node[A](data: A, left: AVLTree[A], right: AVLTree[A]) extends AVLTree[A] { override val balance: Int = right.depth - left.depth override val depth: Int = math.max(left.depth, right.depth) + 1 @@ -205,6 +210,9 @@ private case class Node[A](val data: A, val left: AVLTree[A], val right: AVLTree } } +/** + * @deprecated("AVLTree and its related classes are being removed from the standard library since they're not different enough from RedBlackTree to justify keeping them.", "2.11.0") + */ private class AVLIterator[A](root: Node[A]) extends Iterator[A] { val stack = mutable.ArrayStack[Node[A]](root) diveLeft() @@ -220,11 +228,11 @@ private class AVLIterator[A](root: Node[A]) extends Iterator[A] { private def engageRight(): Unit = { if (Leaf != stack.head.right) { val right: Node[A] = stack.head.right.asInstanceOf[Node[A]] - stack.pop + stack.pop() stack.push(right) diveLeft() } else - stack.pop + stack.pop() } override def hasNext: Boolean = !stack.isEmpty diff --git a/src/library/scala/collection/mutable/AnyRefMap.scala b/src/library/scala/collection/mutable/AnyRefMap.scala new file mode 100644 index 0000000000..47fb66744e --- /dev/null +++ b/src/library/scala/collection/mutable/AnyRefMap.scala @@ -0,0 +1,459 @@ +package scala +package collection +package mutable + +import generic.CanBuildFrom + +/** This class implements mutable maps with `AnyRef` keys based on a hash table with open addressing. + * + * Basic map operations on single entries, including `contains` and `get`, + * are typically significantly faster with `AnyRefMap` than [[HashMap]]. + * Note that numbers and characters are not handled specially in AnyRefMap; + * only plain `equals` and `hashCode` are used in comparisons. + * + * Methods that traverse or regenerate the map, including `foreach` and `map`, + * are not in general faster than with `HashMap`. The methods `foreachKey`, + * `foreachValue`, `mapValuesNow`, and `transformValues` are, however, faster + * than alternative ways to achieve the same functionality. + * + * Maps with open addressing may become less efficient at lookup after + * repeated addition/removal of elements. Although `AnyRefMap` makes a + * decent attempt to remain efficient regardless, calling `repack` + * on a map that will no longer have elements removed but will be + * used heavily may save both time and storage space. + * + * This map is not intended to contain more than 2^29^ entries (approximately + * 500 million). The maximum capacity is 2^30^, but performance will degrade + * rapidly as 2^30^ is approached. + * + */ +final class AnyRefMap[K <: AnyRef, V] private[collection] (defaultEntry: K => V, initialBufferSize: Int, initBlank: Boolean) +extends AbstractMap[K, V] + with Map[K, V] + with MapLike[K, V, AnyRefMap[K, V]] +{ + import AnyRefMap._ + def this() = this(AnyRefMap.exceptionDefault, 16, true) + + /** Creates a new `AnyRefMap` that returns default values according to a supplied key-value mapping. */ + def this(defaultEntry: K => V) = this(defaultEntry, 16, true) + + /** Creates a new `AnyRefMap` with an initial buffer of specified size. + * + * An `AnyRefMap` can typically contain half as many elements as its buffer size + * before it requires resizing. + */ + def this(initialBufferSize: Int) = this(AnyRefMap.exceptionDefault, initialBufferSize, true) + + /** Creates a new `AnyRefMap` with specified default values and initial buffer size. */ + def this(defaultEntry: K => V, initialBufferSize: Int) = this(defaultEntry, initialBufferSize, true) + + private[this] var mask = 0 + private[this] var _size = 0 + private[this] var _vacant = 0 + private[this] var _hashes: Array[Int] = null + private[this] var _keys: Array[AnyRef] = null + private[this] var _values: Array[AnyRef] = null + + if (initBlank) defaultInitialize(initialBufferSize) + + private[this] def defaultInitialize(n: Int) { + mask = + if (n<0) 0x7 + else (((1 << (32 - java.lang.Integer.numberOfLeadingZeros(n-1))) - 1) & 0x3FFFFFFF) | 0x7 + _hashes = new Array[Int](mask+1) + _keys = new Array[AnyRef](mask+1) + _values = new Array[AnyRef](mask+1) + } + + private[collection] def initializeTo( + m: Int, sz: Int, vc: Int, hz: Array[Int], kz: Array[AnyRef], vz: Array[AnyRef] + ) { + mask = m; _size = sz; _vacant = vc; _hashes = hz; _keys = kz; _values = vz + } + + override def size: Int = _size + override def empty: AnyRefMap[K,V] = new AnyRefMap(defaultEntry) + + private def imbalanced: Boolean = + (_size + _vacant) > 0.5*mask || _vacant > _size + + private def hashOf(key: K): Int = { + if (key eq null) 0x41081989 + else { + val h = key.hashCode + // Part of the MurmurHash3 32 bit finalizer + val i = (h ^ (h >>> 16)) * 0x85EBCA6B + val j = (i ^ (i >>> 13)) + if (j==0) 0x41081989 else j & 0x7FFFFFFF + } + } + + private def seekEntry(h: Int, k: AnyRef): Int = { + var e = h & mask + var x = 0 + var g = 0 + while ({ g = _hashes(e); g != 0}) { + if (g == h && { val q = _keys(e); (q eq k) || ((q ne null) && (q equals k)) }) return e + x += 1 + e = (e + 2*(x+1)*x - 3) & mask + } + e | MissingBit + } + + private def seekEntryOrOpen(h: Int, k: AnyRef): Int = { + var e = h & mask + var x = 0 + var g = 0 + var o = -1 + while ({ g = _hashes(e); g != 0}) { + if (g == h && { val q = _keys(e); (q eq k) || ((q ne null) && (q equals k)) }) return e + else if (o == -1 && g+g == 0) o = e + x += 1 + e = (e + 2*(x+1)*x - 3) & mask + } + if (o >= 0) o | MissVacant else e | MissingBit + } + + override def contains(key: K): Boolean = seekEntry(hashOf(key), key) >= 0 + + override def get(key: K): Option[V] = { + val i = seekEntry(hashOf(key), key) + if (i < 0) None else Some(_values(i).asInstanceOf[V]) + } + + override def getOrElse[V1 >: V](key: K, default: => V1): V1 = { + val i = seekEntry(hashOf(key), key) + if (i < 0) default else _values(i).asInstanceOf[V] + } + + override def getOrElseUpdate(key: K, defaultValue: => V): V = { + val h = hashOf(key) + var i = seekEntryOrOpen(h, key) + if (i < 0) { + // It is possible that the default value computation was side-effecting + // Our hash table may have resized or even contain what we want now + // (but if it does, we'll replace it) + val value = { + val oh = _hashes + val ans = defaultValue + if (oh ne _hashes) { + i = seekEntryOrOpen(h, key) + if (i >= 0) _size -= 1 + } + ans + } + _size += 1 + val j = i & IndexMask + _hashes(j) = h + _keys(j) = key.asInstanceOf[AnyRef] + _values(j) = value.asInstanceOf[AnyRef] + if ((i & VacantBit) != 0) _vacant -= 1 + else if (imbalanced) repack() + value + } + else _values(i).asInstanceOf[V] + } + + /** Retrieves the value associated with a key, or the default for that type if none exists + * (null for AnyRef, 0 for floats and integers). + * + * Note: this is the fastest way to retrieve a value that may or + * may not exist, if the default null/zero is acceptable. For key/value + * pairs that do exist, `apply` (i.e. `map(key)`) is equally fast. + */ + def getOrNull(key: K): V = { + val i = seekEntry(hashOf(key), key) + (if (i < 0) null else _values(i)).asInstanceOf[V] + } + + /** Retrieves the value associated with a key. + * If the key does not exist in the map, the `defaultEntry` for that key + * will be returned instead; an exception will be thrown if no + * `defaultEntry` was supplied. + */ + override def apply(key: K): V = { + val i = seekEntry(hashOf(key), key) + if (i < 0) defaultEntry(key) else _values(i).asInstanceOf[V] + } + + /** Defers to defaultEntry to find a default value for the key. Throws an + * exception if no other default behavior was specified. + */ + override def default(key: K) = defaultEntry(key) + + private def repack(newMask: Int) { + val oh = _hashes + val ok = _keys + val ov = _values + mask = newMask + _hashes = new Array[Int](mask+1) + _keys = new Array[AnyRef](mask+1) + _values = new Array[AnyRef](mask+1) + _vacant = 0 + var i = 0 + while (i < oh.length) { + val h = oh(i) + if (h+h != 0) { + var e = h & mask + var x = 0 + while (_hashes(e) != 0) { x += 1; e = (e + 2*(x+1)*x - 3) & mask } + _hashes(e) = h + _keys(e) = ok(i) + _values(e) = ov(i) + } + i += 1 + } + } + + /** Repacks the contents of this `AnyRefMap` for maximum efficiency of lookup. + * + * For maps that undergo a complex creation process with both addition and + * removal of keys, and then are used heavily with no further removal of + * elements, calling `repack` after the end of the creation can result in + * improved performance. Repacking takes time proportional to the number + * of entries in the map. + */ + def repack() { + var m = mask + if (_size + _vacant >= 0.5*mask && !(_vacant > 0.2*mask)) m = ((m << 1) + 1) & IndexMask + while (m > 8 && 8*_size < m) m = m >>> 1 + repack(m) + } + + override def put(key: K, value: V): Option[V] = { + val h = hashOf(key) + val k = key + var i = seekEntryOrOpen(h, k) + if (i < 0) { + val j = i & IndexMask + _hashes(j) = h + _keys(j) = k + _values(j) = value.asInstanceOf[AnyRef] + _size += 1 + if ((i & VacantBit) != 0) _vacant -= 1 + else if (imbalanced) repack() + None + } + else { + val ans = Some(_values(i).asInstanceOf[V]) + _hashes(i) = h + _keys(i) = k + _values(i) = value.asInstanceOf[AnyRef] + ans + } + } + + /** Updates the map to include a new key-value pair. + * + * This is the fastest way to add an entry to an `AnyRefMap`. + */ + override def update(key: K, value: V): Unit = { + val h = hashOf(key) + val k = key + var i = seekEntryOrOpen(h, k) + if (i < 0) { + val j = i & IndexMask + _hashes(j) = h + _keys(j) = k + _values(j) = value.asInstanceOf[AnyRef] + _size += 1 + if ((i & VacantBit) != 0) _vacant -= 1 + else if (imbalanced) repack() + } + else { + _hashes(i) = h + _keys(i) = k + _values(i) = value.asInstanceOf[AnyRef] + } + } + + /** Adds a new key/value pair to this map and returns the map. */ + def +=(key: K, value: V): this.type = { update(key, value); this } + + def +=(kv: (K, V)): this.type = { update(kv._1, kv._2); this } + + def -=(key: K): this.type = { + val i = seekEntry(hashOf(key), key) + if (i >= 0) { + _size -= 1 + _vacant += 1 + _hashes(i) = Int.MinValue + _keys(i) = null + _values(i) = null + } + this + } + + def iterator: Iterator[(K, V)] = new Iterator[(K, V)] { + private[this] val hz = _hashes + private[this] val kz = _keys + private[this] val vz = _values + + private[this] var index = 0 + + def hasNext: Boolean = index<hz.length && { + var h = hz(index) + while (h+h == 0) { + index += 1 + if (index >= hz.length) return false + h = hz(index) + } + true + } + + def next: (K, V) = { + if (hasNext) { + val ans = (kz(index).asInstanceOf[K], vz(index).asInstanceOf[V]) + index += 1 + ans + } + else throw new NoSuchElementException("next") + } + } + + override def foreach[A](f: ((K,V)) => A) { + var i = 0 + var e = _size + while (e > 0) { + while(i < _hashes.length && { val h = _hashes(i); h+h == 0 && i < _hashes.length}) i += 1 + if (i < _hashes.length) { + f((_keys(i).asInstanceOf[K], _values(i).asInstanceOf[V])) + i += 1 + e -= 1 + } + else return + } + } + + override def clone(): AnyRefMap[K, V] = { + val hz = java.util.Arrays.copyOf(_hashes, _hashes.length) + val kz = java.util.Arrays.copyOf(_keys, _keys.length) + val vz = java.util.Arrays.copyOf(_values, _values.length) + val arm = new AnyRefMap[K, V](defaultEntry, 1, false) + arm.initializeTo(mask, _size, _vacant, hz, kz, vz) + arm + } + + private[this] def foreachElement[A,B](elems: Array[AnyRef], f: A => B) { + var i,j = 0 + while (i < _hashes.length & j < _size) { + val h = _hashes(i) + if (h+h != 0) { + j += 1 + f(elems(i).asInstanceOf[A]) + } + i += 1 + } + } + + /** Applies a function to all keys of this map. */ + def foreachKey[A](f: K => A) { foreachElement[K,A](_keys, f) } + + /** Applies a function to all values of this map. */ + def foreachValue[A](f: V => A) { foreachElement[V,A](_values, f) } + + /** Creates a new `AnyRefMap` with different values. + * Unlike `mapValues`, this method generates a new + * collection immediately. + */ + def mapValuesNow[V1](f: V => V1): AnyRefMap[K, V1] = { + val arm = new AnyRefMap[K,V1](AnyRefMap.exceptionDefault, 1, false) + val hz = java.util.Arrays.copyOf(_hashes, _hashes.length) + val kz = java.util.Arrays.copyOf(_keys, _keys.length) + val vz = new Array[AnyRef](_values.length) + var i,j = 0 + while (i < _hashes.length & j < _size) { + val h = _hashes(i) + if (h+h != 0) { + j += 1 + vz(i) = f(_values(i).asInstanceOf[V]).asInstanceOf[AnyRef] + } + i += 1 + } + arm.initializeTo(mask, _size, _vacant, hz, kz, vz) + arm + } + + /** Applies a transformation function to all values stored in this map. + * Note: the default, if any, is not transformed. + */ + def transformValues(f: V => V): this.type = { + var i,j = 0 + while (i < _hashes.length & j < _size) { + val h = _hashes(i) + if (h+h != 0) { + j += 1 + _values(i) = f(_values(i).asInstanceOf[V]).asInstanceOf[AnyRef] + } + i += 1 + } + this + } + +} + +object AnyRefMap { + private final val IndexMask = 0x3FFFFFFF + private final val MissingBit = 0x80000000 + private final val VacantBit = 0x40000000 + private final val MissVacant = 0xC0000000 + + private val exceptionDefault = (k: Any) => throw new NoSuchElementException(if (k == null) "(null)" else k.toString) + + implicit def canBuildFrom[K <: AnyRef, V, J <: AnyRef, U]: CanBuildFrom[AnyRefMap[K,V], (J, U), AnyRefMap[J,U]] = + new CanBuildFrom[AnyRefMap[K,V], (J, U), AnyRefMap[J,U]] { + def apply(from: AnyRefMap[K,V]): AnyRefMapBuilder[J, U] = apply() + def apply(): AnyRefMapBuilder[J, U] = new AnyRefMapBuilder[J, U] + } + + final class AnyRefMapBuilder[K <: AnyRef, V] extends Builder[(K, V), AnyRefMap[K, V]] { + private[collection] var elems: AnyRefMap[K, V] = new AnyRefMap[K, V] + def +=(entry: (K, V)): this.type = { + elems += entry + this + } + def clear() { elems = new AnyRefMap[K, V] } + def result(): AnyRefMap[K, V] = elems + } + + /** Creates a new `AnyRefMap` with zero or more key/value pairs. */ + def apply[K <: AnyRef, V](elems: (K, V)*): AnyRefMap[K, V] = { + val sz = if (elems.hasDefiniteSize) elems.size else 4 + val arm = new AnyRefMap[K, V](sz * 2) + elems.foreach{ case (k,v) => arm(k) = v } + if (arm.size < (sz>>3)) arm.repack() + arm + } + + /** Creates a new empty `AnyRefMap`. */ + def empty[K <: AnyRef, V]: AnyRefMap[K, V] = new AnyRefMap[K, V] + + /** Creates a new empty `AnyRefMap` with the supplied default */ + def withDefault[K <: AnyRef, V](default: K => V): AnyRefMap[K, V] = new AnyRefMap[K, V](default) + + /** Creates a new `AnyRefMap` from arrays of keys and values. + * Equivalent to but more efficient than `AnyRefMap((keys zip values): _*)`. + */ + def fromZip[K <: AnyRef, V](keys: Array[K], values: Array[V]): AnyRefMap[K, V] = { + val sz = math.min(keys.length, values.length) + val arm = new AnyRefMap[K, V](sz * 2) + var i = 0 + while (i < sz) { arm(keys(i)) = values(i); i += 1 } + if (arm.size < (sz>>3)) arm.repack() + arm + } + + /** Creates a new `AnyRefMap` from keys and values. + * Equivalent to but more efficient than `AnyRefMap((keys zip values): _*)`. + */ + def fromZip[K <: AnyRef, V](keys: Iterable[K], values: Iterable[V]): AnyRefMap[K, V] = { + val sz = math.min(keys.size, values.size) + val arm = new AnyRefMap[K, V](sz * 2) + val ki = keys.iterator + val vi = values.iterator + while (ki.hasNext && vi.hasNext) arm(ki.next) = vi.next + if (arm.size < (sz >> 3)) arm.repack() + arm + } +} diff --git a/src/library/scala/collection/mutable/ArrayBuffer.scala b/src/library/scala/collection/mutable/ArrayBuffer.scala index f1cfd2d69a..2d43b352c5 100644 --- a/src/library/scala/collection/mutable/ArrayBuffer.scala +++ b/src/library/scala/collection/mutable/ArrayBuffer.scala @@ -8,7 +8,8 @@ -package scala.collection +package scala +package collection package mutable import generic._ diff --git a/src/library/scala/collection/mutable/ArrayBuilder.scala b/src/library/scala/collection/mutable/ArrayBuilder.scala index 0ce2cda32c..6e53824cbe 100644 --- a/src/library/scala/collection/mutable/ArrayBuilder.scala +++ b/src/library/scala/collection/mutable/ArrayBuilder.scala @@ -6,12 +6,10 @@ ** |/ ** \* */ - - -package scala.collection +package scala +package collection package mutable -import generic._ import scala.reflect.ClassTag import scala.runtime.ScalaRunTime @@ -54,6 +52,7 @@ object ArrayBuilder { * * @tparam T type of elements for the array builder, subtype of `AnyRef` with a `ClassTag` context bound. */ + @deprecatedInheritance("ArrayBuilder.ofRef is an internal implementation not intended for subclassing.", "2.11.0") class ofRef[T <: AnyRef : ClassTag] extends ArrayBuilder[T] { private var elems: Array[T] = _ @@ -118,6 +117,7 @@ object ArrayBuilder { } /** A class for array builders for arrays of `byte`s. */ + @deprecatedInheritance("ArrayBuilder.ofByte is an internal implementation not intended for subclassing.", "2.11.0") class ofByte extends ArrayBuilder[Byte] { private var elems: Array[Byte] = _ @@ -182,6 +182,7 @@ object ArrayBuilder { } /** A class for array builders for arrays of `short`s. */ + @deprecatedInheritance("ArrayBuilder.ofShort is an internal implementation not intended for subclassing.", "2.11.0") class ofShort extends ArrayBuilder[Short] { private var elems: Array[Short] = _ @@ -246,6 +247,7 @@ object ArrayBuilder { } /** A class for array builders for arrays of `char`s. */ + @deprecatedInheritance("ArrayBuilder.ofChar is an internal implementation not intended for subclassing.", "2.11.0") class ofChar extends ArrayBuilder[Char] { private var elems: Array[Char] = _ @@ -310,6 +312,7 @@ object ArrayBuilder { } /** A class for array builders for arrays of `int`s. */ + @deprecatedInheritance("ArrayBuilder.ofInt is an internal implementation not intended for subclassing.", "2.11.0") class ofInt extends ArrayBuilder[Int] { private var elems: Array[Int] = _ @@ -374,6 +377,7 @@ object ArrayBuilder { } /** A class for array builders for arrays of `long`s. */ + @deprecatedInheritance("ArrayBuilder.ofLong is an internal implementation not intended for subclassing.", "2.11.0") class ofLong extends ArrayBuilder[Long] { private var elems: Array[Long] = _ @@ -438,6 +442,7 @@ object ArrayBuilder { } /** A class for array builders for arrays of `float`s. */ + @deprecatedInheritance("ArrayBuilder.ofFloat is an internal implementation not intended for subclassing.", "2.11.0") class ofFloat extends ArrayBuilder[Float] { private var elems: Array[Float] = _ @@ -502,6 +507,7 @@ object ArrayBuilder { } /** A class for array builders for arrays of `double`s. */ + @deprecatedInheritance("ArrayBuilder.ofDouble is an internal implementation not intended for subclassing.", "2.11.0") class ofDouble extends ArrayBuilder[Double] { private var elems: Array[Double] = _ @@ -630,6 +636,7 @@ object ArrayBuilder { } /** A class for array builders for arrays of `Unit` type. */ + @deprecatedInheritance("ArrayBuilder.ofUnit is an internal implementation not intended for subclassing.", "2.11.0") class ofUnit extends ArrayBuilder[Unit] { private var elems: Array[Unit] = _ diff --git a/src/library/scala/collection/mutable/ArrayLike.scala b/src/library/scala/collection/mutable/ArrayLike.scala index 31f3d2a497..80b38a847a 100644 --- a/src/library/scala/collection/mutable/ArrayLike.scala +++ b/src/library/scala/collection/mutable/ArrayLike.scala @@ -6,14 +6,13 @@ ** |/ ** \* */ - - -package scala.collection +package scala +package collection package mutable -import generic._ -/** A common supertrait of `ArrayOps` and `WrappedArray` that factors out most - * operations on arrays and wrapped arrays. +/** A common supertrait of `ArrayOps` and `WrappedArray` that factors out the + * `deep` method for arrays and wrapped arrays and serves as a marker trait + * for array wrappers. * * @tparam A type of the elements contained in the array like object. * @tparam Repr the type of the actual collection containing the elements. diff --git a/src/library/scala/collection/mutable/ArrayOps.scala b/src/library/scala/collection/mutable/ArrayOps.scala index 25ba7e4ce6..00491ef20e 100644 --- a/src/library/scala/collection/mutable/ArrayOps.scala +++ b/src/library/scala/collection/mutable/ArrayOps.scala @@ -33,6 +33,7 @@ import parallel.mutable.ParArray * @define mayNotTerminateInf * @define willNotTerminateInf */ +@deprecatedInheritance("ArrayOps will be sealed to facilitate greater flexibility with array/collections integration in future releases.", "2.11.0") trait ArrayOps[T] extends Any with ArrayLike[T, Array[T]] with CustomParallelizable[T, ParArray[T]] { private def elementClass: Class[_] = @@ -52,6 +53,20 @@ trait ArrayOps[T] extends Any with ArrayLike[T, Array[T]] with CustomParalleliza super.toArray[U] } + def :+[B >: T: ClassTag](elem: B): Array[B] = { + val result = Array.ofDim[B](repr.length + 1) + Array.copy(repr, 0, result, 0, repr.length) + result(repr.length) = elem + result + } + + def +:[B >: T: ClassTag](elem: B): Array[B] = { + val result = Array.ofDim[B](repr.length + 1) + result(0) = elem + Array.copy(repr, 0, result, 1, repr.length) + result + } + override def par = ParArray.handoff(repr) /** Flattens a two-dimensional array by concatenating all its rows @@ -66,7 +81,7 @@ trait ArrayOps[T] extends Any with ArrayLike[T, Array[T]] with CustomParalleliza b.sizeHint(map{case is: scala.collection.IndexedSeq[_] => is.size case _ => 0}.sum) for (xs <- this) b ++= asTrav(xs) - b.result + b.result() } /** Transposes a two dimensional array. @@ -92,6 +107,69 @@ trait ArrayOps[T] extends Any with ArrayLike[T, Array[T]] with CustomParalleliza bb.result() } } + + /** Converts an array of pairs into an array of first elements and an array of second elements. + * + * @tparam T1 the type of the first half of the element pairs + * @tparam T2 the type of the second half of the element pairs + * @param asPair an implicit conversion which asserts that the element type + * of this Array is a pair. + * @param ct1 a class tag for T1 type parameter that is required to create an instance + * of Array[T1] + * @param ct2 a class tag for T2 type parameter that is required to create an instance + * of Array[T2] + * @return a pair of Arrays, containing, respectively, the first and second half + * of each element pair of this Array. + */ + // implementation NOTE: ct1 and ct2 can't be written as context bounds because desugared + // implicits are put in front of asPair parameter that is supposed to guide type inference + def unzip[T1, T2](implicit asPair: T => (T1, T2), ct1: ClassTag[T1], ct2: ClassTag[T2]): (Array[T1], Array[T2]) = { + val a1 = new Array[T1](length) + val a2 = new Array[T2](length) + var i = 0 + while (i < length) { + val e = apply(i) + a1(i) = e._1 + a2(i) = e._2 + i += 1 + } + (a1, a2) + } + + /** Converts an array of triples into three arrays, one containing the elements from each position of the triple. + * + * @tparam T1 the type of the first of three elements in the triple + * @tparam T2 the type of the second of three elements in the triple + * @tparam T3 the type of the third of three elements in the triple + * @param asTriple an implicit conversion which asserts that the element type + * of this Array is a triple. + * @param ct1 a class tag for T1 type parameter that is required to create an instance + * of Array[T1] + * @param ct2 a class tag for T2 type parameter that is required to create an instance + * of Array[T2] + * @param ct3 a class tag for T3 type parameter that is required to create an instance + * of Array[T3] + * @return a triple of Arrays, containing, respectively, the first, second, and third + * elements from each element triple of this Array. + */ + // implementation NOTE: ct1, ct2, ct3 can't be written as context bounds because desugared + // implicits are put in front of asPair parameter that is supposed to guide type inference + def unzip3[T1, T2, T3](implicit asTriple: T => (T1, T2, T3), ct1: ClassTag[T1], ct2: ClassTag[T2], + ct3: ClassTag[T3]): (Array[T1], Array[T2], Array[T3]) = { + val a1 = new Array[T1](length) + val a2 = new Array[T2](length) + val a3 = new Array[T3](length) + var i = 0 + while (i < length) { + val e = apply(i) + a1(i) = e._1 + a2(i) = e._2 + a3(i) = e._3 + i += 1 + } + (a1, a2, a3) + } + def seq = thisCollection diff --git a/src/library/scala/collection/mutable/ArraySeq.scala b/src/library/scala/collection/mutable/ArraySeq.scala index 33f6949662..577a838315 100644 --- a/src/library/scala/collection/mutable/ArraySeq.scala +++ b/src/library/scala/collection/mutable/ArraySeq.scala @@ -8,7 +8,8 @@ -package scala.collection +package scala +package collection package mutable import generic._ @@ -90,7 +91,7 @@ extends AbstractSeq[A] } override def clone(): ArraySeq[A] = { - val cloned = array.clone.asInstanceOf[Array[AnyRef]] + val cloned = array.clone().asInstanceOf[Array[AnyRef]] new ArraySeq[A](length) { override val array = cloned } diff --git a/src/library/scala/collection/mutable/ArrayStack.scala b/src/library/scala/collection/mutable/ArrayStack.scala index 670558ab06..fec2da8839 100644 --- a/src/library/scala/collection/mutable/ArrayStack.scala +++ b/src/library/scala/collection/mutable/ArrayStack.scala @@ -150,14 +150,14 @@ extends AbstractSeq[T] * * @param f The function to drain to. */ - def drain(f: T => Unit) = while (!isEmpty) f(pop) + def drain(f: T => Unit) = while (!isEmpty) f(pop()) /** Pushes all the provided elements in the traversable object onto the stack. * * @param xs The source of elements to push. * @return A reference to this stack. */ - override def ++=(xs: TraversableOnce[T]): this.type = { xs.seq foreach += ; this } + override def ++=(xs: TraversableOnce[T]): this.type = { xs foreach += ; this } /** Does the same as `push`, but returns the updated stack. * @@ -190,7 +190,7 @@ extends AbstractSeq[T] * * @param f The function to apply to the top two elements. */ - def combine(f: (T, T) => T): Unit = push(f(pop, pop)) + def combine(f: (T, T) => T): Unit = push(f(pop(), pop())) /** Repeatedly combine the top elements of the stack until the stack contains only * one element. diff --git a/src/library/scala/collection/mutable/BitSet.scala b/src/library/scala/collection/mutable/BitSet.scala index 2a535a799c..43d23acc1a 100644 --- a/src/library/scala/collection/mutable/BitSet.scala +++ b/src/library/scala/collection/mutable/BitSet.scala @@ -8,11 +8,12 @@ -package scala.collection +package scala +package collection package mutable import generic._ -import BitSetLike.{LogWL, updateArray} +import BitSetLike.{LogWL, MaxSize, updateArray} /** A class for mutable bitsets. * @@ -36,7 +37,7 @@ import BitSetLike.{LogWL, updateArray} * @define willNotTerminateInf */ @SerialVersionUID(8483111450368547763L) -class BitSet(protected var elems: Array[Long]) extends AbstractSet[Int] +class BitSet(protected final var elems: Array[Long]) extends AbstractSet[Int] with SortedSet[Int] with scala.collection.BitSet with BitSetLike[BitSet] @@ -53,19 +54,27 @@ class BitSet(protected var elems: Array[Long]) extends AbstractSet[Int] def this() = this(0) + @deprecatedOverriding("Internal implementation does not admit sensible overriding of this method.", "2.11.0") protected def nwords = elems.length + + @deprecatedOverriding("Internal implementation does not admit sensible overriding of this method.", "2.11.0") protected def word(idx: Int): Long = if (idx < nwords) elems(idx) else 0L - private def updateWord(idx: Int, w: Long) { + protected final def updateWord(idx: Int, w: Long) { + ensureCapacity(idx) + elems(idx) = w + } + + protected final def ensureCapacity(idx: Int) { + require(idx < MaxSize) if (idx >= nwords) { var newlen = nwords - while (idx >= newlen) newlen = newlen * 2 + while (idx >= newlen) newlen = (newlen * 2) min MaxSize val elems1 = new Array[Long](newlen) Array.copy(elems, 0, elems1, 0, nwords) elems = elems1 } - elems(idx) = w } protected def fromBitMaskNoCopy(words: Array[Long]): BitSet = new BitSet(words) @@ -89,9 +98,57 @@ class BitSet(protected var elems: Array[Long]) extends AbstractSet[Int] } else false } + @deprecatedOverriding("Override add to prevent += and add from exhibiting different behavior.", "2.11.0") def += (elem: Int): this.type = { add(elem); this } + + @deprecatedOverriding("Override add to prevent += and add from exhibiting different behavior.", "2.11.0") def -= (elem: Int): this.type = { remove(elem); this } + /** Updates this bitset to the union with another bitset by performing a bitwise "or". + * + * @param other the bitset to form the union with. + * @return the bitset itself. + */ + def |= (other: BitSet): this.type = { + ensureCapacity(other.nwords) + for (i <- 0 until other.nwords) + elems(i) = elems(i) | other.word(i) + this + } + /** Updates this bitset to the intersection with another bitset by performing a bitwise "and". + * + * @param other the bitset to form the intersection with. + * @return the bitset itself. + */ + def &= (other: BitSet): this.type = { + ensureCapacity(other.nwords) + for (i <- 0 until other.nwords) + elems(i) = elems(i) & other.word(i) + this + } + /** Updates this bitset to the symmetric difference with another bitset by performing a bitwise "xor". + * + * @param other the bitset to form the symmetric difference with. + * @return the bitset itself. + */ + def ^= (other: BitSet): this.type = { + ensureCapacity(other.nwords) + for (i <- 0 until other.nwords) + elems(i) = elems(i) ^ other.word(i) + this + } + /** Updates this bitset to the difference with another bitset by performing a bitwise "and-not". + * + * @param other the bitset to form the difference with. + * @return the bitset itself. + */ + def &~= (other: BitSet): this.type = { + ensureCapacity(other.nwords) + for (i <- 0 until other.nwords) + elems(i) = elems(i) & ~other.word(i) + this + } + override def clear() { elems = new Array[Long](elems.length) } diff --git a/src/library/scala/collection/mutable/Buffer.scala b/src/library/scala/collection/mutable/Buffer.scala index 230799c6f3..7ec7b06333 100644 --- a/src/library/scala/collection/mutable/Buffer.scala +++ b/src/library/scala/collection/mutable/Buffer.scala @@ -8,7 +8,8 @@ -package scala.collection +package scala +package collection package mutable import generic._ @@ -45,4 +46,4 @@ object Buffer extends SeqFactory[Buffer] { } /** Explicit instantiation of the `Buffer` trait to reduce class file size in subclasses. */ -private[scala] abstract class AbstractBuffer[A] extends AbstractSeq[A] with Buffer[A] +abstract class AbstractBuffer[A] extends AbstractSeq[A] with Buffer[A] diff --git a/src/library/scala/collection/mutable/BufferLike.scala b/src/library/scala/collection/mutable/BufferLike.scala index 5935a2858a..3c57387c03 100644 --- a/src/library/scala/collection/mutable/BufferLike.scala +++ b/src/library/scala/collection/mutable/BufferLike.scala @@ -8,7 +8,8 @@ -package scala.collection +package scala +package collection package mutable import generic._ @@ -183,6 +184,7 @@ trait BufferLike[A, +This <: BufferLike[A, This] with Buffer[A]] * * @param cmd the message to send. */ + @deprecated("Scripting is deprecated.", "2.11.0") def <<(cmd: Message[A]): Unit = cmd match { case Include(Start, x) => prepend(x) case Include(End, x) => append(x) @@ -198,7 +200,7 @@ trait BufferLike[A, +This <: BufferLike[A, This] with Buffer[A]] case Remove(Index(n), x) => if (this(n) == x) remove(n) case Remove(NoLo, x) => this -= x - case Reset() => clear + case Reset() => clear() case s: Script[_] => s.iterator foreach << case _ => throw new UnsupportedOperationException("message " + cmd + " not understood") } @@ -209,9 +211,11 @@ trait BufferLike[A, +This <: BufferLike[A, This] with Buffer[A]] */ override def stringPrefix: String = "Buffer" - /** Provide a read-only view of this buffer as a sequence - * @return A sequence which refers to this buffer for all its operations. + /** Returns the current evolving(!) state of this buffer as a read-only sequence. + * + * @return A sequence that forwards to this buffer for all its operations. */ + @deprecated("The returned sequence changes as this buffer is mutated. For an immutable copy, use, e.g., toList.", "2.11.0") def readOnly: scala.collection.Seq[A] = toSeq /** Creates a new collection containing both the elements of this collection and the provided @@ -260,6 +264,6 @@ trait BufferLike[A, +This <: BufferLike[A, This] with Buffer[A]] override def clone(): This = { val bf = newBuilder bf ++= this - bf.result.asInstanceOf[This] + bf.result().asInstanceOf[This] } } diff --git a/src/library/scala/collection/mutable/BufferProxy.scala b/src/library/scala/collection/mutable/BufferProxy.scala index 37aa1862fa..d9632cce91 100644 --- a/src/library/scala/collection/mutable/BufferProxy.scala +++ b/src/library/scala/collection/mutable/BufferProxy.scala @@ -6,12 +6,10 @@ ** |/ ** \* */ - - -package scala.collection +package scala +package collection package mutable -import generic._ import script._ /** This is a simple proxy class for <a href="Buffer.html" @@ -28,6 +26,7 @@ import script._ * @define Coll `BufferProxy` * @define coll buffer proxy */ +@deprecated("Proxying is deprecated due to lack of use and compiler-level support.", "2.11.0") trait BufferProxy[A] extends Buffer[A] with Proxy { def self: Buffer[A] @@ -127,12 +126,13 @@ trait BufferProxy[A] extends Buffer[A] with Proxy { /** Clears the buffer contents. */ - def clear() { self.clear } + def clear() { self.clear() } /** Send a message to this scriptable object. * * @param cmd the message to send. */ + @deprecated("Scripting is deprecated.", "2.11.0") override def <<(cmd: Message[A]) { self << cmd } /** Return a clone of this buffer. diff --git a/src/library/scala/collection/mutable/Builder.scala b/src/library/scala/collection/mutable/Builder.scala index 5c0681df1d..75560580cc 100644 --- a/src/library/scala/collection/mutable/Builder.scala +++ b/src/library/scala/collection/mutable/Builder.scala @@ -121,7 +121,7 @@ trait Builder[-Elem, +To] extends Growable[Elem] { override def ++=(xs: TraversableOnce[Elem]): this.type = { self ++= xs; this } override def sizeHint(size: Int) = self.sizeHint(size) override def sizeHintBounded(size: Int, boundColl: TraversableLike[_, _]) = self.sizeHintBounded(size, boundColl) - def result: NewTo = f(self.result) + def result: NewTo = f(self.result()) } } diff --git a/src/library/scala/collection/mutable/Cloneable.scala b/src/library/scala/collection/mutable/Cloneable.scala index dadcd36257..8b2f3f70de 100644 --- a/src/library/scala/collection/mutable/Cloneable.scala +++ b/src/library/scala/collection/mutable/Cloneable.scala @@ -8,7 +8,8 @@ -package scala.collection +package scala +package collection package mutable /** A trait for cloneable collections. diff --git a/src/library/scala/collection/mutable/ConcurrentMap.scala b/src/library/scala/collection/mutable/ConcurrentMap.scala deleted file mode 100644 index 5b5d738d03..0000000000 --- a/src/library/scala/collection/mutable/ConcurrentMap.scala +++ /dev/null @@ -1,90 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2010-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala.collection -package mutable - -/** A template trait for mutable maps that allow concurrent access. - * - * $concurrentmapinfo - * - * @since 2.8 - * @see [[http://docs.scala-lang.org/overviews/collections/concrete-mutable-collection-classes.html#concurrent_maps "Scala's Collection Library overview"]] - * section on `Concurrent Maps` for more information. - * - * @tparam A the key type of the map - * @tparam B the value type of the map - * - * @define Coll `ConcurrentMap` - * @define coll concurrent map - * @define concurrentmapinfo - * This is a base trait for all Scala concurrent map implementations. It - * provides all of the methods a `Map` does, with the difference that all the - * changes are atomic. It also describes methods specific to concurrent maps. - * - * '''Note''': The concurrent maps do not accept `'''null'''` for keys or values. - * - * @define atomicop - * This is an atomic operation. - */ -@deprecated("Use `scala.collection.concurrent.Map` instead.", "2.10.0") -trait ConcurrentMap[A, B] extends Map[A, B] { - - /** - * Associates the given key with a given value, unless the key was already - * associated with some other value. - * - * $atomicop - * - * @param k key with which the specified value is to be associated with - * @param v value to be associated with the specified key - * @return `Some(oldvalue)` if there was a value `oldvalue` previously - * associated with the specified key, or `None` if there was no - * mapping for the specified key - */ - def putIfAbsent(k: A, v: B): Option[B] - - /** - * Removes the entry for the specified key if its currently mapped to the - * specified value. - * - * $atomicop - * - * @param k key for which the entry should be removed - * @param v value expected to be associated with the specified key if - * the removal is to take place - * @return `true` if the removal took place, `false` otherwise - */ - def remove(k: A, v: B): Boolean - - /** - * Replaces the entry for the given key only if it was previously mapped to - * a given value. - * - * $atomicop - * - * @param k key for which the entry should be replaced - * @param oldvalue value expected to be associated with the specified key - * if replacing is to happen - * @param newvalue value to be associated with the specified key - * @return `true` if the entry was replaced, `false` otherwise - */ - def replace(k: A, oldvalue: B, newvalue: B): Boolean - - /** - * Replaces the entry for the given key only if it was previously mapped - * to some value. - * - * $atomicop - * - * @param k key for which the entry should be replaced - * @param v value to be associated with the specified key - * @return `Some(v)` if the given key was previously mapped to some value `v`, or `None` otherwise - */ - def replace(k: A, v: B): Option[B] -} diff --git a/src/library/scala/collection/mutable/DefaultEntry.scala b/src/library/scala/collection/mutable/DefaultEntry.scala index f14cb4ac2b..66db45866c 100644 --- a/src/library/scala/collection/mutable/DefaultEntry.scala +++ b/src/library/scala/collection/mutable/DefaultEntry.scala @@ -6,7 +6,8 @@ ** |/ ** \* */ -package scala.collection +package scala +package collection package mutable /** Class used internally for default map model. diff --git a/src/library/scala/collection/mutable/DefaultMapModel.scala b/src/library/scala/collection/mutable/DefaultMapModel.scala index 903f117466..0088620540 100644 --- a/src/library/scala/collection/mutable/DefaultMapModel.scala +++ b/src/library/scala/collection/mutable/DefaultMapModel.scala @@ -8,7 +8,8 @@ -package scala.collection +package scala +package collection package mutable /** This class is used internally. It implements the mutable `Map` @@ -18,6 +19,7 @@ package mutable * @version 1.0, 08/07/2003 * @since 1 */ +@deprecated("This trait will be removed.", "2.11.0") trait DefaultMapModel[A, B] extends Map[A, B] { type Entry = DefaultEntry[A, B] diff --git a/src/library/scala/collection/mutable/DoubleLinkedList.scala b/src/library/scala/collection/mutable/DoubleLinkedList.scala index 18a1e234f6..671b79f8c2 100644 --- a/src/library/scala/collection/mutable/DoubleLinkedList.scala +++ b/src/library/scala/collection/mutable/DoubleLinkedList.scala @@ -8,7 +8,8 @@ -package scala.collection +package scala +package collection package mutable import generic._ @@ -40,6 +41,7 @@ import generic._ * @define mayNotTerminateInf * @define willNotTerminateInf */ +@deprecated("Low-level linked lists are deprecated due to idiosyncracies in interface and incomplete features.", "2.11.0") @SerialVersionUID(-8144992287952814767L) class DoubleLinkedList[A]() extends AbstractSeq[A] with LinearSeq[A] @@ -68,7 +70,7 @@ class DoubleLinkedList[A]() extends AbstractSeq[A] override def clone(): DoubleLinkedList[A] = { val builder = newBuilder builder ++= this - builder.result + builder.result() } } @@ -76,6 +78,7 @@ class DoubleLinkedList[A]() extends AbstractSeq[A] * @define coll double linked list * @define Coll `DoubleLinkedList` */ +@deprecated("Low-level linked lists are deprecated.", "2.11.0") object DoubleLinkedList extends SeqFactory[DoubleLinkedList] { /** $genericCanBuildFromInfo */ implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, DoubleLinkedList[A]] = ReusableCBF.asInstanceOf[GenericCanBuildFrom[A]] diff --git a/src/library/scala/collection/mutable/DoubleLinkedListLike.scala b/src/library/scala/collection/mutable/DoubleLinkedListLike.scala index 3f223f30ec..a43fe34c99 100644 --- a/src/library/scala/collection/mutable/DoubleLinkedListLike.scala +++ b/src/library/scala/collection/mutable/DoubleLinkedListLike.scala @@ -8,7 +8,8 @@ -package scala.collection +package scala +package collection package mutable import scala.annotation.migration @@ -55,6 +56,7 @@ import scala.annotation.migration * @define Coll `DoubleLinkedList` * @define coll double linked list */ +@deprecated("Low-level linked lists are deprecated due to idiosyncracies in interface and incomplete features.", "2.11.0") trait DoubleLinkedListLike[A, This <: Seq[A] with DoubleLinkedListLike[A, This]] extends SeqLike[A, This] with LinkedListLike[A, This] { self => /** A reference to the node in the linked list preceeding the current node. */ diff --git a/src/library/scala/collection/mutable/FlatHashTable.scala b/src/library/scala/collection/mutable/FlatHashTable.scala index 91e95e039b..25cc873b82 100644 --- a/src/library/scala/collection/mutable/FlatHashTable.scala +++ b/src/library/scala/collection/mutable/FlatHashTable.scala @@ -6,18 +6,16 @@ ** |/ ** \* */ - -package scala.collection +package scala +package collection package mutable - /** An implementation class backing a `HashSet`. * * This trait is used internally. It can be mixed in with various collections relying on * hash table as an implementation. * * @define coll flat hash table - * @define cannotStoreNull '''Note''': A $coll cannot store `null` elements. * @since 2.3 * @tparam A the type of the elements contained in the $coll. */ @@ -78,7 +76,7 @@ trait FlatHashTable[A] extends FlatHashTable.HashUtils[A] { assert(size >= 0) table = new Array(capacity(sizeForThreshold(size, _loadFactor))) - threshold = newThreshold(_loadFactor, table.size) + threshold = newThreshold(_loadFactor, table.length) seedvalue = in.readInt() @@ -87,9 +85,9 @@ trait FlatHashTable[A] extends FlatHashTable.HashUtils[A] { var index = 0 while (index < size) { - val elem = in.readObject().asInstanceOf[A] + val elem = entryToElem(in.readObject()) f(elem) - addEntry(elem) + addElem(elem) index += 1 } } @@ -109,61 +107,80 @@ trait FlatHashTable[A] extends FlatHashTable.HashUtils[A] { } /** Finds an entry in the hash table if such an element exists. */ - protected def findEntry(elem: A): Option[A] = { - val entry = findEntryImpl(elem) - if (null == entry) None else Some(entry.asInstanceOf[A]) - } + @deprecatedOverriding("Internal implementation does not admit sensible overriding of this method.", "2.11.0") + protected def findEntry(elem: A): Option[A] = + findElemImpl(elem) match { + case null => None + case entry => Some(entryToElem(entry)) + } + /** Checks whether an element is contained in the hash table. */ - protected def containsEntry(elem: A): Boolean = { - null != findEntryImpl(elem) + @deprecatedOverriding("Internal implementation does not admit sensible overriding of this method.", "2.11.0") + protected def containsElem(elem: A): Boolean = { + null != findElemImpl(elem) } - private def findEntryImpl(elem: A): AnyRef = { - var h = index(elemHashCode(elem)) - var entry = table(h) - while (null != entry && entry != elem) { + private def findElemImpl(elem: A): AnyRef = { + val searchEntry = elemToEntry(elem) + var h = index(searchEntry.hashCode) + var curEntry = table(h) + while (null != curEntry && curEntry != searchEntry) { h = (h + 1) % table.length - entry = table(h) + curEntry = table(h) } - entry + curEntry + } + + /** Add elem if not yet in table. + * @return Returns `true` if a new elem was added, `false` otherwise. + */ + protected def addElem(elem: A) : Boolean = { + addEntry(elemToEntry(elem)) } - /** Add entry if not yet in table. - * @return Returns `true` if a new entry was added, `false` otherwise. + /** + * Add an entry (an elem converted to an entry via elemToEntry) if not yet in + * table. + * @return Returns `true` if a new elem was added, `false` otherwise. */ - protected def addEntry(elem: A) : Boolean = { - var h = index(elemHashCode(elem)) - var entry = table(h) - while (null != entry) { - if (entry == elem) return false + protected def addEntry(newEntry : AnyRef) : Boolean = { + var h = index(newEntry.hashCode) + var curEntry = table(h) + while (null != curEntry) { + if (curEntry == newEntry) return false h = (h + 1) % table.length - entry = table(h) + curEntry = table(h) //Statistics.collisions += 1 } - table(h) = elem.asInstanceOf[AnyRef] + table(h) = newEntry tableSize = tableSize + 1 nnSizeMapAdd(h) if (tableSize >= threshold) growTable() true + } - /** Removes an entry from the hash table, returning an option value with the element, or `None` if it didn't exist. */ - protected def removeEntry(elem: A) : Option[A] = { + /** + * Removes an elem from the hash table returning true if the element was found (and thus removed) + * or false if it didn't exist. + */ + protected def removeElem(elem: A) : Boolean = { if (tableDebug) checkConsistent() def precedes(i: Int, j: Int) = { val d = table.length >> 1 if (i <= j) j - i < d else i - j > d } - var h = index(elemHashCode(elem)) - var entry = table(h) - while (null != entry) { - if (entry == elem) { + val removalEntry = elemToEntry(elem) + var h = index(removalEntry.hashCode) + var curEntry = table(h) + while (null != curEntry) { + if (curEntry == removalEntry) { var h0 = h var h1 = (h0 + 1) % table.length while (null != table(h1)) { - val h2 = index(elemHashCode(table(h1).asInstanceOf[A])) + val h2 = index(table(h1).hashCode) //Console.println("shift at "+h1+":"+table(h1)+" with h2 = "+h2+"? "+(h2 != h1)+precedes(h2, h0)+table.length) if (h2 != h1 && precedes(h2, h0)) { //Console.println("shift "+h1+" to "+h0+"!") @@ -176,12 +193,12 @@ trait FlatHashTable[A] extends FlatHashTable.HashUtils[A] { tableSize -= 1 nnSizeMapRemove(h0) if (tableDebug) checkConsistent() - return Some(entry.asInstanceOf[A]) + return true } h = (h + 1) % table.length - entry = table(h) + curEntry = table(h) } - None + false } protected def iterator: Iterator[A] = new AbstractIterator[A] { @@ -191,8 +208,8 @@ trait FlatHashTable[A] extends FlatHashTable.HashUtils[A] { i < table.length } def next(): A = - if (hasNext) { i += 1; table(i - 1).asInstanceOf[A] } - else Iterator.empty.next + if (hasNext) { i += 1; entryToElem(table(i - 1)) } + else Iterator.empty.next() } private def growTable() { @@ -205,7 +222,7 @@ trait FlatHashTable[A] extends FlatHashTable.HashUtils[A] { var i = 0 while (i < oldtable.length) { val entry = oldtable(i) - if (null != entry) addEntry(entry.asInstanceOf[A]) + if (null != entry) addEntry(entry) i += 1 } if (tableDebug) checkConsistent() @@ -213,10 +230,11 @@ trait FlatHashTable[A] extends FlatHashTable.HashUtils[A] { private def checkConsistent() { for (i <- 0 until table.length) - if (table(i) != null && !containsEntry(table(i).asInstanceOf[A])) - assert(false, i+" "+table(i)+" "+table.mkString) + if (table(i) != null && !containsElem(entryToElem(table(i)))) + assert(assertion = false, i+" "+table(i)+" "+table.mkString) } + /* Size map handling code */ /* @@ -232,15 +250,18 @@ trait FlatHashTable[A] extends FlatHashTable.HashUtils[A] { * where sizeMapBucketSize == 4. * */ + @deprecatedOverriding("Internal implementation does not admit sensible overriding of this method.", "2.11.0") protected def nnSizeMapAdd(h: Int) = if (sizemap ne null) { val p = h >> sizeMapBucketBitSize sizemap(p) += 1 } + @deprecatedOverriding("Internal implementation does not admit sensible overriding of this method.", "2.11.0") protected def nnSizeMapRemove(h: Int) = if (sizemap ne null) { sizemap(h >> sizeMapBucketBitSize) -= 1 } + @deprecatedOverriding("Internal implementation does not admit sensible overriding of this method.", "2.11.0") protected def nnSizeMapReset(tableLength: Int) = if (sizemap ne null) { val nsize = calcSizeMapSize(tableLength) if (sizemap.length != nsize) sizemap = new Array[Int](nsize) @@ -249,14 +270,17 @@ trait FlatHashTable[A] extends FlatHashTable.HashUtils[A] { private[collection] final def totalSizeMapBuckets = (table.length - 1) / sizeMapBucketSize + 1 + @deprecatedOverriding("Internal implementation does not admit sensible overriding of this method.", "2.11.0") protected def calcSizeMapSize(tableLength: Int) = (tableLength >> sizeMapBucketBitSize) + 1 // discards the previous sizemap and only allocates a new one + @deprecatedOverriding("Internal implementation does not admit sensible overriding of this method.", "2.11.0") protected def sizeMapInit(tableLength: Int) { sizemap = new Array[Int](calcSizeMapSize(tableLength)) } // discards the previous sizemap and populates the new one + @deprecatedOverriding("Internal implementation does not admit sensible overriding of this method.", "2.11.0") protected def sizeMapInitAndRebuild() { // first allocate sizeMapInit(table.length) @@ -265,7 +289,7 @@ trait FlatHashTable[A] extends FlatHashTable.HashUtils[A] { val totalbuckets = totalSizeMapBuckets var bucketidx = 0 var tableidx = 0 - var tbl = table + val tbl = table var tableuntil = sizeMapBucketSize min tbl.length while (bucketidx < totalbuckets) { var currbucketsz = 0 @@ -341,7 +365,7 @@ trait FlatHashTable[A] extends FlatHashTable.HashUtils[A] { seedvalue = c.seedvalue sizemap = c.sizemap } - if (alwaysInitSizeMap && sizemap == null) sizeMapInitAndRebuild + if (alwaysInitSizeMap && sizemap == null) sizeMapInitAndRebuild() } } @@ -359,6 +383,11 @@ private[collection] object FlatHashTable { override def initialValue = new scala.util.Random } + private object NullSentinel { + override def hashCode = 0 + override def toString = "NullSentinel" + } + /** The load factor for the hash table; must be < 500 (0.5) */ def defaultLoadFactor: Int = 450 @@ -386,10 +415,6 @@ private[collection] object FlatHashTable { // so that: protected final def sizeMapBucketSize = 1 << sizeMapBucketBitSize - protected def elemHashCode(elem: A) = - if (elem == null) throw new IllegalArgumentException("Flat hash tables cannot contain null elements.") - else elem.hashCode() - protected final def improve(hcode: Int, seed: Int) = { //var h: Int = hcode + ~(hcode << 9) //h = h ^ (h >>> 14) @@ -404,6 +429,19 @@ private[collection] object FlatHashTable { val rotated = (improved >>> rotation) | (improved << (32 - rotation)) rotated } + + /** + * Elems have type A, but we store AnyRef in the table. Plus we need to deal with + * null elems, which need to be stored as NullSentinel + */ + protected final def elemToEntry(elem : A) : AnyRef = + if (null == elem) NullSentinel else elem.asInstanceOf[AnyRef] + + /** + * Does the inverse translation of elemToEntry + */ + protected final def entryToElem(entry : AnyRef) : A = + (if (entry.isInstanceOf[NullSentinel.type]) null else entry).asInstanceOf[A] } } diff --git a/src/library/scala/collection/mutable/GenIterable.scala.disabled b/src/library/scala/collection/mutable/GenIterable.scala.disabled deleted file mode 100644 index 9acfccdae8..0000000000 --- a/src/library/scala/collection/mutable/GenIterable.scala.disabled +++ /dev/null @@ -1,37 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala.collection -package mutable - - -import generic._ - - -/** A base trait for iterable collections that can be mutated. - * - * $possiblyparinfo - * - * $iterableInfo - */ -trait GenIterable[A] extends GenTraversable[A] - with scala.collection.GenIterable[A] - with scala.collection.GenIterableLike[A, GenIterable[A]] -// with GenericTraversableTemplate[A, GenIterable] -{ - def seq: Iterable[A] - //override def companion: GenericCompanion[GenIterable] = GenIterable -} - - -// object GenIterable extends TraversableFactory[GenIterable] { -// implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, GenIterable[A]] = ReusableCBF.asInstanceOf[GenericCanBuildFrom[A]] -// def newBuilder[A]: Builder[A, GenIterable[A]] = Iterable.newBuilder -// } - - diff --git a/src/library/scala/collection/mutable/GenMap.scala.disabled b/src/library/scala/collection/mutable/GenMap.scala.disabled deleted file mode 100644 index e4fd1dad64..0000000000 --- a/src/library/scala/collection/mutable/GenMap.scala.disabled +++ /dev/null @@ -1,40 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - - -package scala.collection -package mutable - - -import generic._ - - -/** A base trait for maps that can be mutated. - * $possiblyparinfo - * $mapNote - * $mapTags - * @since 1.0 - * @author Matthias Zenger - */ -trait GenMap[A, B] -extends GenIterable[(A, B)] - with scala.collection.GenMap[A, B] - with scala.collection.GenMapLike[A, B, GenMap[A, B]] -{ - def seq: Map[A, B] -} - - -// object GenMap extends MapFactory[GenMap] { -// def empty[A, B]: Map[A, B] = Map.empty - -// /** $mapCanBuildFromInfo */ -// implicit def canBuildFrom[A, B]: CanBuildFrom[Coll, (A, B), GenMap[A, B]] = new MapCanBuildFrom[A, B] -// } - diff --git a/src/library/scala/collection/mutable/GenSeq.scala.disabled b/src/library/scala/collection/mutable/GenSeq.scala.disabled deleted file mode 100644 index ec904723a5..0000000000 --- a/src/library/scala/collection/mutable/GenSeq.scala.disabled +++ /dev/null @@ -1,44 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - - -package scala.collection -package mutable - - -import generic._ - - -/** A subtrait of `collection.GenSeq` which represents sequences - * that can be mutated. - * - * $possiblyparinfo - * - * $seqInfo - * - * The class adds an `update` method to `collection.Seq`. - * - * @define Coll `mutable.Seq` - * @define coll mutable sequence - */ -trait GenSeq[A] extends GenIterable[A] - with scala.collection.GenSeq[A] - with scala.collection.GenSeqLike[A, GenSeq[A]] -// with GenericTraversableTemplate[A, GenSeq] -{ - //override def companion: GenericCompanion[GenSeq] = GenSeq - def seq: Seq[A] -} - - -// object GenSeq extends SeqFactory[GenSeq] { -// implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, GenSeq[A]] = ReusableCBF.asInstanceOf[GenericCanBuildFrom[A]] -// def newBuilder[A]: Builder[A, GenSeq[A]] = Seq.newBuilder -// } - diff --git a/src/library/scala/collection/mutable/GenSet.scala.disabled b/src/library/scala/collection/mutable/GenSet.scala.disabled deleted file mode 100644 index dec20e2a46..0000000000 --- a/src/library/scala/collection/mutable/GenSet.scala.disabled +++ /dev/null @@ -1,46 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - - -package scala.collection -package mutable - - - -import generic._ - - -/** A generic trait for mutable sets. - * - * $possiblyparinfo - * $setNote - * $setTags - * - * @since 1.0 - * @author Matthias Zenger - * @define Coll `mutable.Set` - * @define coll mutable set - */ -trait GenSet[A] extends GenIterable[A] - with Growable[A] - with scala.collection.GenSet[A] - with scala.collection.GenSetLike[A, GenSet[A]] -// with GenericSetTemplate[A, GenSet] -{ - //override def companion: GenericCompanion[GenSet] = GenSet - def seq: Set[A] -} - - -// object GenSet extends TraversableFactory[GenSet] { -// implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, GenSet[A]] = ReusableCBF.asInstanceOf[GenericCanBuildFrom[A]] -// def newBuilder[A]: Builder[A, GenSet[A]] = Set.newBuilder -// } - - diff --git a/src/library/scala/collection/mutable/GenTraversable.scala.disabled b/src/library/scala/collection/mutable/GenTraversable.scala.disabled deleted file mode 100644 index 2453e2ce87..0000000000 --- a/src/library/scala/collection/mutable/GenTraversable.scala.disabled +++ /dev/null @@ -1,38 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - - -package scala.collection -package mutable - - -import generic._ - - -/** A trait for traversable collections that can be mutated. - * - * $possiblyparinfo - * - * $traversableInfo - * @define mutability mutable - */ -trait GenTraversable[A] extends scala.collection.GenTraversable[A] - with scala.collection.GenTraversableLike[A, GenTraversable[A]] -// with GenericTraversableTemplate[A, GenTraversable] - with Mutable -{ - def seq: Traversable[A] - //override def companion: GenericCompanion[GenTraversable] = GenTraversable -} - -// object GenTraversable extends TraversableFactory[GenTraversable] { -// implicit def canBuildFrom[A] = ReusableCBF.asInstanceOf[GenericCanBuildFrom[A]] -// def newBuilder[A] = Traversable.newBuilder -// } - diff --git a/src/library/scala/collection/mutable/GrowingBuilder.scala b/src/library/scala/collection/mutable/GrowingBuilder.scala index ba7ea60df1..c4b5e546aa 100644 --- a/src/library/scala/collection/mutable/GrowingBuilder.scala +++ b/src/library/scala/collection/mutable/GrowingBuilder.scala @@ -6,7 +6,8 @@ ** |/ ** \* */ -package scala.collection +package scala +package collection package mutable import generic._ diff --git a/src/library/scala/collection/mutable/HashEntry.scala b/src/library/scala/collection/mutable/HashEntry.scala index 5cd976eb47..4c0f6a93e8 100644 --- a/src/library/scala/collection/mutable/HashEntry.scala +++ b/src/library/scala/collection/mutable/HashEntry.scala @@ -5,7 +5,8 @@ ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** \* */ -package scala.collection +package scala +package collection package mutable /** Class used internally. diff --git a/src/library/scala/collection/mutable/HashMap.scala b/src/library/scala/collection/mutable/HashMap.scala index 3cd7f07d83..6fca75ffea 100644 --- a/src/library/scala/collection/mutable/HashMap.scala +++ b/src/library/scala/collection/mutable/HashMap.scala @@ -6,7 +6,8 @@ ** |/ ** \* */ -package scala.collection +package scala +package collection package mutable import generic._ @@ -93,9 +94,9 @@ extends AbstractMap[A, B] def -=(key: A): this.type = { removeEntry(key); this } - def iterator = entriesIterator map {e => (e.key, e.value)} + def iterator = entriesIterator map (e => ((e.key, e.value))) - override def foreach[C](f: ((A, B)) => C): Unit = foreachEntry(e => f(e.key, e.value)) + override def foreach[C](f: ((A, B)) => C): Unit = foreachEntry(e => f((e.key, e.value))) /* Override to avoid tuple allocation in foreach */ override def keySet: scala.collection.Set[A] = new DefaultKeySet { @@ -111,21 +112,21 @@ extends AbstractMap[A, B] override def keysIterator: Iterator[A] = new AbstractIterator[A] { val iter = entriesIterator def hasNext = iter.hasNext - def next() = iter.next.key + def next() = iter.next().key } /* Override to avoid tuple allocation */ override def valuesIterator: Iterator[B] = new AbstractIterator[B] { val iter = entriesIterator def hasNext = iter.hasNext - def next() = iter.next.value + def next() = iter.next().value } /** Toggles whether a size map is used to track hash map statistics. */ def useSizeMap(t: Boolean) = if (t) { - if (!isSizeMapDefined) sizeMapInitAndRebuild - } else sizeMapDisable + if (!isSizeMapDefined) sizeMapInitAndRebuild() + } else sizeMapDisable() protected def createNewEntry[B1](key: A, value: B1): Entry = { new Entry(key, value.asInstanceOf[B]) diff --git a/src/library/scala/collection/mutable/HashSet.scala b/src/library/scala/collection/mutable/HashSet.scala index c60e363f8f..886fee5a59 100644 --- a/src/library/scala/collection/mutable/HashSet.scala +++ b/src/library/scala/collection/mutable/HashSet.scala @@ -8,7 +8,8 @@ -package scala.collection +package scala +package collection package mutable import generic._ @@ -16,8 +17,6 @@ import scala.collection.parallel.mutable.ParHashSet /** This class implements mutable sets using a hashtable. * - * $cannotStoreNull - * * @author Matthias Zenger * @author Martin Odersky * @version 2.0, 31/12/2006 @@ -55,17 +54,17 @@ extends AbstractSet[A] override def size: Int = tableSize - def contains(elem: A): Boolean = containsEntry(elem) + def contains(elem: A): Boolean = containsElem(elem) - def += (elem: A): this.type = { addEntry(elem); this } + def += (elem: A): this.type = { addElem(elem); this } - def -= (elem: A): this.type = { removeEntry(elem); this } + def -= (elem: A): this.type = { removeElem(elem); this } override def par = new ParHashSet(hashTableContents) - override def add(elem: A): Boolean = addEntry(elem) + override def add(elem: A): Boolean = addElem(elem) - override def remove(elem: A): Boolean = removeEntry(elem).isDefined + override def remove(elem: A): Boolean = removeElem(elem) override def clear() { clearTable() } @@ -75,8 +74,8 @@ extends AbstractSet[A] var i = 0 val len = table.length while (i < len) { - val elem = table(i) - if (elem ne null) f(elem.asInstanceOf[A]) + val curEntry = table(i) + if (curEntry ne null) f(entryToElem(curEntry)) i += 1 } } @@ -94,8 +93,8 @@ extends AbstractSet[A] /** Toggles whether a size map is used to track hash map statistics. */ def useSizeMap(t: Boolean) = if (t) { - if (!isSizeMapDefined) sizeMapInitAndRebuild - } else sizeMapDisable + if (!isSizeMapDefined) sizeMapInitAndRebuild() + } else sizeMapDisable() } diff --git a/src/library/scala/collection/mutable/HashTable.scala b/src/library/scala/collection/mutable/HashTable.scala index 8fef1be66b..65d9c35052 100644 --- a/src/library/scala/collection/mutable/HashTable.scala +++ b/src/library/scala/collection/mutable/HashTable.scala @@ -8,7 +8,8 @@ -package scala.collection +package scala +package collection package mutable /** This class can be used to construct data structures that are based @@ -96,7 +97,7 @@ trait HashTable[A, Entry >: Null <: HashEntry[A, Entry]] extends HashTable.HashU val smDefined = in.readBoolean() table = new Array(capacity(sizeForThreshold(_loadFactor, size))) - threshold = newThreshold(_loadFactor, table.size) + threshold = newThreshold(_loadFactor, table.length) if (smDefined) sizeMapInit(table.length) else sizemap = null @@ -126,6 +127,7 @@ trait HashTable[A, Entry >: Null <: HashEntry[A, Entry]] extends HashTable.HashU /** Find entry with given key in table, null if not found. */ + @deprecatedOverriding("No sensible way to override findEntry as private findEntry0 is used in multiple places internally.", "2.11.0") protected def findEntry(key: A): Entry = findEntry0(key, index(elemHashCode(key))) @@ -138,6 +140,7 @@ trait HashTable[A, Entry >: Null <: HashEntry[A, Entry]] extends HashTable.HashU /** Add entry to table * pre: no entry with same key exists */ + @deprecatedOverriding("No sensible way to override addEntry as private addEntry0 is used in multiple places internally.", "2.11.0") protected def addEntry(e: Entry) { addEntry0(e, index(elemHashCode(e.key))) } @@ -171,6 +174,7 @@ trait HashTable[A, Entry >: Null <: HashEntry[A, Entry]] extends HashTable.HashU /** Remove entry from table if present. */ + @deprecatedOverriding("Internal implementation does not admit sensible overriding of this method.", "2.11.0") protected def removeEntry(key: A) : Entry = { val h = index(elemHashCode(key)) var e = table(h).asInstanceOf[Entry] @@ -281,14 +285,17 @@ trait HashTable[A, Entry >: Null <: HashEntry[A, Entry]] extends HashTable.HashU * is converted into a parallel hash table, the size map is initialized, as it will be needed * there. */ + @deprecatedOverriding("Internal implementation does not admit sensible overriding of this method.", "2.11.0") protected def nnSizeMapAdd(h: Int) = if (sizemap ne null) { sizemap(h >> sizeMapBucketBitSize) += 1 } + @deprecatedOverriding("Internal implementation does not admit sensible overriding of this method.", "2.11.0") protected def nnSizeMapRemove(h: Int) = if (sizemap ne null) { sizemap(h >> sizeMapBucketBitSize) -= 1 } + @deprecatedOverriding("Internal implementation does not admit sensible overriding of this method.", "2.11.0") protected def nnSizeMapReset(tableLength: Int) = if (sizemap ne null) { val nsize = calcSizeMapSize(tableLength) if (sizemap.length != nsize) sizemap = new Array[Int](nsize) @@ -297,6 +304,7 @@ trait HashTable[A, Entry >: Null <: HashEntry[A, Entry]] extends HashTable.HashU private[collection] final def totalSizeMapBuckets = if (sizeMapBucketSize < table.length) 1 else table.length / sizeMapBucketSize + @deprecatedOverriding("Internal implementation does not admit sensible overriding of this method.", "2.11.0") protected def calcSizeMapSize(tableLength: Int) = (tableLength >> sizeMapBucketBitSize) + 1 // discards the previous sizemap and only allocates a new one @@ -305,6 +313,7 @@ trait HashTable[A, Entry >: Null <: HashEntry[A, Entry]] extends HashTable.HashU } // discards the previous sizemap and populates the new one + @deprecatedOverriding("Internal implementation does not admit sensible overriding of this method.", "2.11.0") protected def sizeMapInitAndRebuild() { sizeMapInit(table.length) @@ -335,8 +344,10 @@ trait HashTable[A, Entry >: Null <: HashEntry[A, Entry]] extends HashTable.HashU println(sizemap.toList) } + @deprecatedOverriding("Internal implementation does not admit sensible overriding of this method.", "2.11.0") protected def sizeMapDisable() = sizemap = null + @deprecatedOverriding("Internal implementation does not admit sensible overriding of this method.", "2.11.0") protected def isSizeMapDefined = sizemap ne null // override to automatically initialize the size map @@ -365,7 +376,7 @@ trait HashTable[A, Entry >: Null <: HashEntry[A, Entry]] extends HashTable.HashU seedvalue = c.seedvalue sizemap = c.sizemap } - if (alwaysInitSizeMap && sizemap == null) sizeMapInitAndRebuild + if (alwaysInitSizeMap && sizemap == null) sizeMapInitAndRebuild() } private[collection] def hashTableContents = new HashTable.Contents( @@ -382,7 +393,7 @@ private[collection] object HashTable { /** The load factor for the hash table (in 0.001 step). */ private[collection] final def defaultLoadFactor: Int = 750 // corresponds to 75% - private[collection] final def loadFactorDenum = 1000; + private[collection] final def loadFactorDenum = 1000 private[collection] final def newThreshold(_loadFactor: Int, size: Int) = ((size.toLong * _loadFactor) / loadFactorDenum).toInt @@ -457,13 +468,13 @@ private[collection] object HashTable { */ private[collection] def powerOfTwo(target: Int): Int = { /* See http://bits.stephan-brumme.com/roundUpToNextPowerOfTwo.html */ - var c = target - 1; - c |= c >>> 1; - c |= c >>> 2; - c |= c >>> 4; - c |= c >>> 8; - c |= c >>> 16; - c + 1; + var c = target - 1 + c |= c >>> 1 + c |= c >>> 2 + c |= c >>> 4 + c |= c >>> 8 + c |= c >>> 16 + c + 1 } class Contents[A, Entry >: Null <: HashEntry[A, Entry]]( diff --git a/src/library/scala/collection/mutable/History.scala b/src/library/scala/collection/mutable/History.scala index c1d94a904c..19148c0ac2 100644 --- a/src/library/scala/collection/mutable/History.scala +++ b/src/library/scala/collection/mutable/History.scala @@ -1,6 +1,6 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2011, LAMP/tPFL ** +** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/tPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** @@ -8,7 +8,8 @@ -package scala.collection +package scala +package collection package mutable @@ -41,7 +42,7 @@ extends AbstractIterable[(Pub, Evt)] */ def notify(pub: Pub, event: Evt) { if (log.length >= maxHistory) - log.dequeue + log.dequeue() log.enqueue((pub, event)) } @@ -50,7 +51,7 @@ extends AbstractIterable[(Pub, Evt)] def iterator: Iterator[(Pub, Evt)] = log.iterator def events: Iterator[Evt] = log.iterator map (_._2) - def clear() { log.clear } + def clear() { log.clear() } /** Checks if two history objects are structurally identical. * @@ -60,5 +61,5 @@ extends AbstractIterable[(Pub, Evt)] case that: History[_, _] => this.log equals that.log case _ => false } - override def hashCode = log.hashCode + override def hashCode = log.hashCode() } diff --git a/src/library/scala/collection/mutable/ImmutableMapAdaptor.scala b/src/library/scala/collection/mutable/ImmutableMapAdaptor.scala index 755eea831f..9ece8b1335 100644 --- a/src/library/scala/collection/mutable/ImmutableMapAdaptor.scala +++ b/src/library/scala/collection/mutable/ImmutableMapAdaptor.scala @@ -8,7 +8,8 @@ -package scala.collection +package scala +package collection package mutable import scala.annotation.migration @@ -24,6 +25,7 @@ import scala.annotation.migration * @version 2.0, 01/01/2007 * @since 1 */ +@deprecated("Adaptors are inherently unreliable and prone to performance problems.", "2.11.0") class ImmutableMapAdaptor[A, B](protected var imap: immutable.Map[A, B]) extends AbstractMap[A, B] with Map[A, B] diff --git a/src/library/scala/collection/mutable/ImmutableSetAdaptor.scala b/src/library/scala/collection/mutable/ImmutableSetAdaptor.scala index 42c757d3bf..730b22227d 100644 --- a/src/library/scala/collection/mutable/ImmutableSetAdaptor.scala +++ b/src/library/scala/collection/mutable/ImmutableSetAdaptor.scala @@ -6,12 +6,10 @@ ** |/ ** \* */ - - -package scala.collection +package scala +package collection package mutable - /** This class can be used as an adaptor to create mutable sets from * immutable set implementations. Only method `empty` has * to be redefined if the immutable set on which this mutable set is @@ -22,6 +20,7 @@ package mutable * @version 1.0, 21/07/2003 * @since 1 */ +@deprecated("Adaptors are inherently unreliable and prone to performance problems.", "2.11.0") class ImmutableSetAdaptor[A](protected var set: immutable.Set[A]) extends AbstractSet[A] with Set[A] @@ -48,6 +47,4 @@ extends AbstractSet[A] def -=(elem: A): this.type = { set = set - elem; this } override def clear(): Unit = { set = set.empty } - } - diff --git a/src/library/scala/collection/mutable/IndexedSeq.scala b/src/library/scala/collection/mutable/IndexedSeq.scala index 4d094e697b..3d9630eea7 100644 --- a/src/library/scala/collection/mutable/IndexedSeq.scala +++ b/src/library/scala/collection/mutable/IndexedSeq.scala @@ -8,7 +8,8 @@ -package scala.collection +package scala +package collection package mutable import generic._ diff --git a/src/library/scala/collection/mutable/IndexedSeqLike.scala b/src/library/scala/collection/mutable/IndexedSeqLike.scala index f0c31ec7fb..4cf794c32f 100644 --- a/src/library/scala/collection/mutable/IndexedSeqLike.scala +++ b/src/library/scala/collection/mutable/IndexedSeqLike.scala @@ -6,11 +6,9 @@ ** |/ ** \* */ - - -package scala.collection +package scala +package collection package mutable -import generic._ /** A subtrait of scala.collection.IndexedSeq which represents sequences * that can be mutated. diff --git a/src/library/scala/collection/mutable/IndexedSeqOptimized.scala b/src/library/scala/collection/mutable/IndexedSeqOptimized.scala index cb7e8efdc7..09f0712862 100755 --- a/src/library/scala/collection/mutable/IndexedSeqOptimized.scala +++ b/src/library/scala/collection/mutable/IndexedSeqOptimized.scala @@ -6,11 +6,9 @@ ** |/ ** \* */ - - -package scala.collection +package scala +package collection package mutable -import generic._ /** A subtrait of scala.collection.IndexedSeq which represents sequences * that can be mutated. diff --git a/src/library/scala/collection/mutable/IndexedSeqView.scala b/src/library/scala/collection/mutable/IndexedSeqView.scala index cf5166eea8..31a4749960 100644 --- a/src/library/scala/collection/mutable/IndexedSeqView.scala +++ b/src/library/scala/collection/mutable/IndexedSeqView.scala @@ -8,7 +8,8 @@ -package scala.collection +package scala +package collection package mutable import generic._ @@ -82,8 +83,6 @@ self => protected override def newTakenWhile(p: A => Boolean): Transformed[A] = new { val pred = p } with AbstractTransformed[A] with TakenWhile protected override def newReversed: Transformed[A] = new AbstractTransformed[A] with Reversed - private implicit def asThis(xs: Transformed[A]): This = xs.asInstanceOf[This] - override def filter(p: A => Boolean): This = newFiltered(p) override def init: This = newSliced(SliceInterval(0, self.length - 1)) override def drop(n: Int): This = newSliced(SliceInterval(n, self.length)) @@ -94,6 +93,7 @@ self => override def span(p: A => Boolean): (This, This) = (newTakenWhile(p), newDroppedWhile(p)) override def splitAt(n: Int): (This, This) = (take(n), drop(n)) // !!! override def reverse: This = newReversed + override def tail: IndexedSeqView[A, Coll] = if (isEmpty) super.tail else slice(1, length) } /** An object containing the necessary implicit definitions to make diff --git a/src/library/scala/collection/mutable/Iterable.scala b/src/library/scala/collection/mutable/Iterable.scala index b79453e4e9..92313c9ccd 100644 --- a/src/library/scala/collection/mutable/Iterable.scala +++ b/src/library/scala/collection/mutable/Iterable.scala @@ -5,7 +5,8 @@ ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** \* */ -package scala.collection +package scala +package collection package mutable import generic._ @@ -37,4 +38,4 @@ object Iterable extends TraversableFactory[Iterable] { } /** Explicit instantiation of the `Iterable` trait to reduce class file size in subclasses. */ -private[scala] abstract class AbstractIterable[A] extends scala.collection.AbstractIterable[A] with Iterable[A] +abstract class AbstractIterable[A] extends scala.collection.AbstractIterable[A] with Iterable[A] diff --git a/src/library/scala/collection/mutable/LazyBuilder.scala b/src/library/scala/collection/mutable/LazyBuilder.scala index 0b56c86ac4..ebee38b77f 100644 --- a/src/library/scala/collection/mutable/LazyBuilder.scala +++ b/src/library/scala/collection/mutable/LazyBuilder.scala @@ -6,7 +6,8 @@ ** |/ ** \* */ -package scala.collection +package scala +package collection package mutable /** A builder that constructs its result lazily. Iterators or iterables to diff --git a/src/library/scala/collection/mutable/LinearSeq.scala b/src/library/scala/collection/mutable/LinearSeq.scala index f241a2f6d4..3fa10042ef 100644 --- a/src/library/scala/collection/mutable/LinearSeq.scala +++ b/src/library/scala/collection/mutable/LinearSeq.scala @@ -8,7 +8,8 @@ -package scala.collection +package scala +package collection package mutable import generic._ diff --git a/src/library/scala/collection/mutable/LinkedEntry.scala b/src/library/scala/collection/mutable/LinkedEntry.scala index e4e29122d8..296e7fde18 100644 --- a/src/library/scala/collection/mutable/LinkedEntry.scala +++ b/src/library/scala/collection/mutable/LinkedEntry.scala @@ -8,7 +8,8 @@ -package scala.collection +package scala +package collection package mutable /** Class for the linked hash map entry, used internally. diff --git a/src/library/scala/collection/mutable/LinkedHashMap.scala b/src/library/scala/collection/mutable/LinkedHashMap.scala index da2c36ac2d..b64504be3d 100644 --- a/src/library/scala/collection/mutable/LinkedHashMap.scala +++ b/src/library/scala/collection/mutable/LinkedHashMap.scala @@ -8,7 +8,8 @@ -package scala.collection +package scala +package collection package mutable import generic._ @@ -84,7 +85,10 @@ class LinkedHashMap[A, B] extends AbstractMap[A, B] } } + @deprecatedOverriding("+= should not be overridden so it stays consistent with put.", "2.11.0") def += (kv: (A, B)): this.type = { put(kv._1, kv._2); this } + + @deprecatedOverriding("-= should not be overridden so it stays consistent with remove.", "2.11.0") def -=(key: A): this.type = { remove(key); this } def iterator: Iterator[(A, B)] = new AbstractIterator[(A, B)] { @@ -92,33 +96,33 @@ class LinkedHashMap[A, B] extends AbstractMap[A, B] def hasNext = cur ne null def next = if (hasNext) { val res = (cur.key, cur.value); cur = cur.later; res } - else Iterator.empty.next + else Iterator.empty.next() } - + protected class FilteredKeys(p: A => Boolean) extends super.FilteredKeys(p) { override def empty = LinkedHashMap.empty } - + override def filterKeys(p: A => Boolean): scala.collection.Map[A, B] = new FilteredKeys(p) protected class MappedValues[C](f: B => C) extends super.MappedValues[C](f) { override def empty = LinkedHashMap.empty } - + override def mapValues[C](f: B => C): scala.collection.Map[A, C] = new MappedValues(f) - + protected class DefaultKeySet extends super.DefaultKeySet { override def empty = LinkedHashSet.empty } - + override def keySet: scala.collection.Set[A] = new DefaultKeySet - + override def keysIterator: Iterator[A] = new AbstractIterator[A] { private var cur = firstEntry def hasNext = cur ne null def next = if (hasNext) { val res = cur.key; cur = cur.later; res } - else Iterator.empty.next + else Iterator.empty.next() } override def valuesIterator: Iterator[B] = new AbstractIterator[B] { @@ -126,7 +130,7 @@ class LinkedHashMap[A, B] extends AbstractMap[A, B] def hasNext = cur ne null def next = if (hasNext) { val res = cur.value; cur = cur.later; res } - else Iterator.empty.next + else Iterator.empty.next() } override def foreach[U](f: ((A, B)) => U) { diff --git a/src/library/scala/collection/mutable/LinkedHashSet.scala b/src/library/scala/collection/mutable/LinkedHashSet.scala index 1723258433..1768c946ed 100644 --- a/src/library/scala/collection/mutable/LinkedHashSet.scala +++ b/src/library/scala/collection/mutable/LinkedHashSet.scala @@ -7,7 +7,8 @@ \* */ -package scala.collection +package scala +package collection package mutable import generic._ @@ -56,7 +57,10 @@ class LinkedHashSet[A] extends AbstractSet[A] def contains(elem: A): Boolean = findEntry(elem) ne null + @deprecatedOverriding("+= should not be overridden so it stays consistent with add.", "2.11.0") def += (elem: A): this.type = { add(elem); this } + + @deprecatedOverriding("-= should not be overridden so it stays consistent with remove.", "2.11.0") def -= (elem: A): this.type = { remove(elem); this } override def add(elem: A): Boolean = findOrAddEntry(elem, null) eq null @@ -78,9 +82,9 @@ class LinkedHashSet[A] extends AbstractSet[A] def hasNext = cur ne null def next = if (hasNext) { val res = cur.key; cur = cur.later; res } - else Iterator.empty.next + else Iterator.empty.next() } - + override def foreach[U](f: A => U) { var cur = firstEntry while (cur ne null) { diff --git a/src/library/scala/collection/mutable/LinkedList.scala b/src/library/scala/collection/mutable/LinkedList.scala index 29e6fdd375..092698ac0b 100644 --- a/src/library/scala/collection/mutable/LinkedList.scala +++ b/src/library/scala/collection/mutable/LinkedList.scala @@ -8,7 +8,8 @@ -package scala.collection +package scala +package collection package mutable import generic._ @@ -75,6 +76,7 @@ import generic._ * }}} */ @SerialVersionUID(-7308240733518833071L) +@deprecated("Low-level linked lists are deprecated due to idiosyncracies in interface and incomplete features.", "2.11.0") class LinkedList[A]() extends AbstractSeq[A] with LinearSeq[A] with GenericTraversableTemplate[A, LinkedList] @@ -112,6 +114,7 @@ class LinkedList[A]() extends AbstractSeq[A] * @define Coll `LinkedList` * @define coll linked list */ +@deprecated("Low-level linked lists are deprecated.", "2.11.0") object LinkedList extends SeqFactory[LinkedList] { override def empty[A]: LinkedList[A] = new LinkedList[A] implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, LinkedList[A]] = ReusableCBF.asInstanceOf[GenericCanBuildFrom[A]] diff --git a/src/library/scala/collection/mutable/LinkedListLike.scala b/src/library/scala/collection/mutable/LinkedListLike.scala index 4f63ede7ca..987b83d23b 100644 --- a/src/library/scala/collection/mutable/LinkedListLike.scala +++ b/src/library/scala/collection/mutable/LinkedListLike.scala @@ -6,12 +6,10 @@ ** |/ ** \* */ - - -package scala.collection +package scala +package collection package mutable -import generic._ import scala.annotation.tailrec /** This extensible class may be used as a basis for implementing linked @@ -57,6 +55,7 @@ import scala.annotation.tailrec * * }}} */ +@deprecated("Low-level linked lists are deprecated due to idiosyncracies in interface and incomplete features.", "2.11.0") trait LinkedListLike[A, This <: Seq[A] with LinkedListLike[A, This]] extends SeqLike[A, This] { self => var elem: A = _ @@ -188,6 +187,6 @@ trait LinkedListLike[A, This <: Seq[A] with LinkedListLike[A, This]] extends Seq override def clone(): This = { val bf = newBuilder bf ++= this - bf.result + bf.result() } } diff --git a/src/library/scala/collection/mutable/ListBuffer.scala b/src/library/scala/collection/mutable/ListBuffer.scala index 67af4a6bd6..5e838d0d88 100644 --- a/src/library/scala/collection/mutable/ListBuffer.scala +++ b/src/library/scala/collection/mutable/ListBuffer.scala @@ -6,14 +6,14 @@ ** |/ ** \* */ - - -package scala.collection +package scala +package collection package mutable import generic._ import immutable.{List, Nil, ::} import java.io._ +import scala.annotation.migration /** A `Buffer` implementation back up by a list. It provides constant time * prepend and append. Most other operations are linear. @@ -56,12 +56,18 @@ final class ListBuffer[A] import scala.collection.Traversable import scala.collection.immutable.ListSerializeEnd + /** Expected invariants: + * If start.isEmpty, last0 == null + * If start.nonEmpty, last0 != null + * If len == 0, start.isEmpty + * If len > 0, start.nonEmpty + */ private var start: List[A] = Nil private var last0: ::[A] = _ private var exported: Boolean = false private var len = 0 - protected def underlying: immutable.Seq[A] = start + protected def underlying: List[A] = start private def writeObject(out: ObjectOutputStream) { // write start @@ -133,7 +139,7 @@ final class ListBuffer[A] if (n < 0 || n >= len) throw new IndexOutOfBoundsException(n.toString) if (exported) copy() if (n == 0) { - val newElem = new :: (x, start.tail); + val newElem = new :: (x, start.tail) if (last0 eq start) { last0 = newElem } @@ -160,7 +166,7 @@ final class ListBuffer[A] */ def += (x: A): this.type = { if (exported) copy() - if (start.isEmpty) { + if (isEmpty) { last0 = new :: (x, Nil) start = last0 } else { @@ -172,8 +178,11 @@ final class ListBuffer[A] this } - override def ++=(xs: TraversableOnce[A]): this.type = - if (xs.asInstanceOf[AnyRef] eq this) ++= (this take size) else super.++=(xs) + override def ++=(xs: TraversableOnce[A]): this.type = xs match { + case x: AnyRef if x eq this => this ++= (this take size) + case _ => super.++=(xs) + + } override def ++=:(xs: TraversableOnce[A]): this.type = if (xs.asInstanceOf[AnyRef] eq this) ++=: (this take size) else super.++=:(xs) @@ -182,6 +191,7 @@ final class ListBuffer[A] */ def clear() { start = Nil + last0 = null exported = false len = 0 } @@ -195,7 +205,7 @@ final class ListBuffer[A] def +=: (x: A): this.type = { if (exported) copy() val newElem = new :: (x, start) - if (start.isEmpty) last0 = newElem + if (isEmpty) last0 = newElem start = newElem len += 1 this @@ -238,13 +248,22 @@ final class ListBuffer[A] } } + /** Reduce the length of the buffer, and null out last0 + * if this reduces the length to 0. + */ + private def reduceLengthBy(num: Int) { + len -= num + if (len <= 0) // obviously shouldn't be < 0, but still better not to leak + last0 = null + } + /** Removes a given number of elements on a given index position. May take * time linear in the buffer size. * * @param n the index which refers to the first element to remove. * @param count the number of elements to remove. */ - @annotation.migration("Invalid input values will be rejected in future releases.", "2.11") + @migration("Invalid input values will be rejected in future releases.", "2.11") override def remove(n: Int, count: Int) { if (n >= len) return @@ -253,7 +272,6 @@ final class ListBuffer[A] if (exported) copy() val n1 = n max 0 val count1 = count min (len - n1) - var old = start.head if (n1 == 0) { var c = count1 while (c > 0) { @@ -274,7 +292,7 @@ final class ListBuffer[A] c -= 1 } } - len -= count1 + reduceLengthBy(count1) } // Implementation of abstract method in Builder @@ -285,7 +303,7 @@ final class ListBuffer[A] * copied lazily, the first time it is mutated. */ override def toList: List[A] = { - exported = !start.isEmpty + exported = !isEmpty start } @@ -296,7 +314,7 @@ final class ListBuffer[A] * @param xs the list to which elements are prepended */ def prependToList(xs: List[A]): List[A] = { - if (start.isEmpty) xs + if (isEmpty) xs else { if (exported) copy() last0.tl = xs @@ -331,7 +349,7 @@ final class ListBuffer[A] if (last0 eq cursor.tail) last0 = cursor.asInstanceOf[::[A]] cursor.asInstanceOf[::[A]].tl = cursor.tail.tail } - len -= 1 + reduceLengthBy(1) old } @@ -343,11 +361,12 @@ final class ListBuffer[A] */ override def -= (elem: A): this.type = { if (exported) copy() - if (start.isEmpty) {} + if (isEmpty) {} else if (start.head == elem) { start = start.tail - len -= 1 - } else { + reduceLengthBy(1) + } + else { var cursor = start while (!cursor.tail.isEmpty && cursor.tail.head != elem) { cursor = cursor.tail @@ -357,12 +376,18 @@ final class ListBuffer[A] if (z.tl == last0) last0 = z z.tl = cursor.tail.tail - len -= 1 + reduceLengthBy(1) } } this } + /** Returns an iterator over this `ListBuffer`. The iterator will reflect + * changes made to the underlying `ListBuffer` beyond the next element; + * the next element's value is cached so that `hasNext` and `next` are + * guaranteed to be consistent. In particular, an empty `ListBuffer` + * will give an empty iterator even if the `ListBuffer` is later filled. + */ override def iterator: Iterator[A] = new AbstractIterator[A] { // Have to be careful iterating over mutable structures. // This used to have "(cursor ne last0)" as part of its hasNext @@ -371,32 +396,26 @@ final class ListBuffer[A] // a structure while iterating, but we should never return hasNext == true // on exhausted iterators (thus creating exceptions) merely because // values were changed in-place. - var cursor: List[A] = null - var delivered = 0 - - // Note: arguably this should not be a "dynamic test" against - // the present length of the buffer, but fixed at the size of the - // buffer when the iterator is created. At the moment such a - // change breaks tests: see comment on def units in Global.scala. - def hasNext: Boolean = delivered < ListBuffer.this.length + var cursor: List[A] = if (ListBuffer.this.isEmpty) Nil else start + + def hasNext: Boolean = cursor ne Nil def next(): A = - if (!hasNext) - throw new NoSuchElementException("next on empty Iterator") + if (!hasNext) throw new NoSuchElementException("next on empty Iterator") else { - if (cursor eq null) cursor = start - else cursor = cursor.tail - delivered += 1 - cursor.head + val ans = cursor.head + cursor = cursor.tail + ans } } - /** expose the underlying list but do not mark it as exported */ + @deprecated("The result of this method will change along with this buffer, which is often not what's expected.", "2.11.0") override def readOnly: List[A] = start // Private methods /** Copy contents of this buffer */ private def copy() { + if (isEmpty) return var cursor = start val limit = last0.tail clear() diff --git a/src/library/scala/collection/mutable/ListMap.scala b/src/library/scala/collection/mutable/ListMap.scala index 7f05deffc8..2ea5b1fa7c 100644 --- a/src/library/scala/collection/mutable/ListMap.scala +++ b/src/library/scala/collection/mutable/ListMap.scala @@ -8,7 +8,8 @@ -package scala.collection +package scala +package collection package mutable import generic._ @@ -49,7 +50,10 @@ extends AbstractMap[A, B] def get(key: A): Option[B] = elems find (_._1 == key) map (_._2) def iterator: Iterator[(A, B)] = elems.iterator + @deprecatedOverriding("No sensible way to override += as private remove is used in multiple places internally.", "2.11.0") def += (kv: (A, B)) = { elems = remove(kv._1, elems, List()); elems = kv :: elems; siz += 1; this } + + @deprecatedOverriding("No sensible way to override -= as private remove is used in multiple places internally.", "2.11.0") def -= (key: A) = { elems = remove(key, elems, List()); this } @tailrec @@ -60,7 +64,10 @@ extends AbstractMap[A, B] } + @deprecatedOverriding("No sensible way to override as this functionality relies upon access to private methods.", "2.11.0") override def clear() = { elems = List(); siz = 0 } + + @deprecatedOverriding("No sensible way to override as this functionality relies upon access to private methods.", "2.11.0") override def size: Int = siz } diff --git a/src/library/scala/collection/mutable/LongMap.scala b/src/library/scala/collection/mutable/LongMap.scala new file mode 100644 index 0000000000..984ae6f7cc --- /dev/null +++ b/src/library/scala/collection/mutable/LongMap.scala @@ -0,0 +1,569 @@ +package scala +package collection +package mutable + +import generic.CanBuildFrom + +/** This class implements mutable maps with `Long` keys based on a hash table with open addressing. + * + * Basic map operations on single entries, including `contains` and `get`, + * are typically substantially faster with `LongMap` than [[HashMap]]. Methods + * that act on the whole map, including `foreach` and `map` are not in + * general expected to be faster than with a generic map, save for those + * that take particular advantage of the internal structure of the map: + * `foreachKey`, `foreachValue`, `mapValuesNow`, and `transformValues`. + * + * Maps with open addressing may become less efficient at lookup after + * repeated addition/removal of elements. Although `LongMap` makes a + * decent attempt to remain efficient regardless, calling `repack` + * on a map that will no longer have elements removed but will be + * used heavily may save both time and storage space. + * + * This map is not indended to contain more than 2^29 entries (approximately + * 500 million). The maximum capacity is 2^30, but performance will degrade + * rapidly as 2^30 is approached. + * + */ +final class LongMap[V] private[collection] (defaultEntry: Long => V, initialBufferSize: Int, initBlank: Boolean) +extends AbstractMap[Long, V] + with Map[Long, V] + with MapLike[Long, V, LongMap[V]] + with Serializable +{ + import LongMap._ + + def this() = this(LongMap.exceptionDefault, 16, true) + + /** Creates a new `LongMap` that returns default values according to a supplied key-value mapping. */ + def this(defaultEntry: Long => V) = this(defaultEntry, 16, true) + + /** Creates a new `LongMap` with an initial buffer of specified size. + * + * A LongMap can typically contain half as many elements as its buffer size + * before it requires resizing. + */ + def this(initialBufferSize: Int) = this(LongMap.exceptionDefault, initialBufferSize, true) + + /** Creates a new `LongMap` with specified default values and initial buffer size. */ + def this(defaultEntry: Long => V, initialBufferSize: Int) = this(defaultEntry, initialBufferSize, true) + + private[this] var mask = 0 + private[this] var extraKeys: Int = 0 + private[this] var zeroValue: AnyRef = null + private[this] var minValue: AnyRef = null + private[this] var _size = 0 + private[this] var _vacant = 0 + private[this] var _keys: Array[Long] = null + private[this] var _values: Array[AnyRef] = null + + if (initBlank) defaultInitialize(initialBufferSize) + + private[this] def defaultInitialize(n: Int) = { + mask = + if (n<0) 0x7 + else (((1 << (32 - java.lang.Integer.numberOfLeadingZeros(n-1))) - 1) & 0x3FFFFFFF) | 0x7 + _keys = new Array[Long](mask+1) + _values = new Array[AnyRef](mask+1) + } + + private[collection] def initializeTo( + m: Int, ek: Int, zv: AnyRef, mv: AnyRef, sz: Int, vc: Int, kz: Array[Long], vz: Array[AnyRef] + ) { + mask = m; extraKeys = ek; zeroValue = zv; minValue = mv; _size = sz; _vacant = vc; _keys = kz; _values = vz + } + + override def size: Int = _size + (extraKeys+1)/2 + override def empty: LongMap[V] = new LongMap() + + private def imbalanced: Boolean = + (_size + _vacant) > 0.5*mask || _vacant > _size + + private def toIndex(k: Long): Int = { + // Part of the MurmurHash3 32 bit finalizer + val h = ((k ^ (k >>> 32)) & 0xFFFFFFFFL).toInt + var x = (h ^ (h >>> 16)) * 0x85EBCA6B + (x ^ (x >>> 13)) & mask + } + + private def seekEmpty(k: Long): Int = { + var e = toIndex(k) + var x = 0 + while (_keys(e) != 0) { x += 1; e = (e + 2*(x+1)*x - 3) & mask } + e + } + + private def seekEntry(k: Long): Int = { + var e = toIndex(k) + var x = 0 + var q = 0L + while ({ q = _keys(e); if (q==k) return e; q != 0}) { x += 1; e = (e + 2*(x+1)*x - 3) & mask } + e | MissingBit + } + + private def seekEntryOrOpen(k: Long): Int = { + var e = toIndex(k) + var x = 0 + var q = 0L + while ({ q = _keys(e); if (q==k) return e; q+q != 0}) { + x += 1 + e = (e + 2*(x+1)*x - 3) & mask + } + if (q == 0) return e | MissingBit + val o = e | MissVacant + while ({ q = _keys(e); if (q==k) return e; q != 0}) { + x += 1 + e = (e + 2*(x+1)*x - 3) & mask + } + o + } + + override def contains(key: Long): Boolean = { + if (key == -key) (((key>>>63).toInt+1) & extraKeys) != 0 + else seekEntry(key) >= 0 + } + + override def get(key: Long): Option[V] = { + if (key == -key) { + if ((((key>>>63).toInt+1) & extraKeys) == 0) None + else if (key == 0) Some(zeroValue.asInstanceOf[V]) + else Some(minValue.asInstanceOf[V]) + } + else { + val i = seekEntry(key) + if (i < 0) None else Some(_values(i).asInstanceOf[V]) + } + } + + override def getOrElse[V1 >: V](key: Long, default: => V1): V1 = { + if (key == -key) { + if ((((key>>>63).toInt+1) & extraKeys) == 0) default + else if (key == 0) zeroValue.asInstanceOf[V1] + else minValue.asInstanceOf[V1] + } + else { + val i = seekEntry(key) + if (i < 0) default else _values(i).asInstanceOf[V1] + } + } + + override def getOrElseUpdate(key: Long, defaultValue: => V): V = { + if (key == -key) { + val kbits = (key>>>63).toInt + 1 + if ((kbits & extraKeys) == 0) { + val value = defaultValue + extraKeys |= kbits + if (key == 0) zeroValue = value.asInstanceOf[AnyRef] + else minValue = value.asInstanceOf[AnyRef] + value + } + else if (key == 0) zeroValue.asInstanceOf[V] + else minValue.asInstanceOf[V] + } + else { + var i = seekEntryOrOpen(key) + if (i < 0) { + // It is possible that the default value computation was side-effecting + // Our hash table may have resized or even contain what we want now + // (but if it does, we'll replace it) + val value = { + val ok = _keys + val ans = defaultValue + if (ok ne _keys) { + i = seekEntryOrOpen(key) + if (i >= 0) _size -= 1 + } + ans + } + _size += 1 + val j = i & IndexMask + _keys(j) = key + _values(j) = value.asInstanceOf[AnyRef] + if ((i & VacantBit) != 0) _vacant -= 1 + else if (imbalanced) repack() + value + } + else _values(i).asInstanceOf[V] + } + } + + /** Retrieves the value associated with a key, or the default for that type if none exists + * (null for AnyRef, 0 for floats and integers). + * + * Note: this is the fastest way to retrieve a value that may or + * may not exist, if the default null/zero is acceptable. For key/value + * pairs that do exist, `apply` (i.e. `map(key)`) is equally fast. + */ + def getOrNull(key: Long): V = { + if (key == -key) { + if ((((key>>>63).toInt+1) & extraKeys) == 0) null.asInstanceOf[V] + else if (key == 0) zeroValue.asInstanceOf[V] + else minValue.asInstanceOf[V] + } + else { + val i = seekEntry(key) + if (i < 0) null.asInstanceOf[V] else _values(i).asInstanceOf[V] + } + } + + /** Retrieves the value associated with a key. + * If the key does not exist in the map, the `defaultEntry` for that key + * will be returned instead. + */ + override def apply(key: Long): V = { + if (key == -key) { + if ((((key>>>63).toInt+1) & extraKeys) == 0) defaultEntry(key) + else if (key == 0) zeroValue.asInstanceOf[V] + else minValue.asInstanceOf[V] + } + else { + val i = seekEntry(key) + if (i < 0) defaultEntry(key) else _values(i).asInstanceOf[V] + } + } + + /** The user-supplied default value for the key. Throws an exception + * if no other default behavior was specified. + */ + override def default(key: Long) = defaultEntry(key) + + private def repack(newMask: Int) { + val ok = _keys + val ov = _values + mask = newMask + _keys = new Array[Long](mask+1) + _values = new Array[AnyRef](mask+1) + _vacant = 0 + var i = 0 + while (i < ok.length) { + val k = ok(i) + if (k != -k) { + val j = seekEmpty(k) + _keys(j) = k + _values(j) = ov(i) + } + i += 1 + } + } + + /** Repacks the contents of this `LongMap` for maximum efficiency of lookup. + * + * For maps that undergo a complex creation process with both addition and + * removal of keys, and then are used heavily with no further removal of + * elements, calling `repack` after the end of the creation can result in + * improved performance. Repacking takes time proportional to the number + * of entries in the map. + */ + def repack() { + var m = mask + if (_size + _vacant >= 0.5*mask && !(_vacant > 0.2*mask)) m = ((m << 1) + 1) & IndexMask + while (m > 8 && 8*_size < m) m = m >>> 1 + repack(m) + } + + override def put(key: Long, value: V): Option[V] = { + if (key == -key) { + if (key == 0) { + val ans = if ((extraKeys&1) == 1) Some(zeroValue.asInstanceOf[V]) else None + zeroValue = value.asInstanceOf[AnyRef] + extraKeys |= 1 + ans + } + else { + val ans = if ((extraKeys&2) == 1) Some(minValue.asInstanceOf[V]) else None + minValue = value.asInstanceOf[AnyRef] + extraKeys |= 2 + ans + } + } + else { + val i = seekEntryOrOpen(key) + if (i < 0) { + val j = i & IndexMask + _keys(j) = key + _values(j) = value.asInstanceOf[AnyRef] + _size += 1 + if ((i & VacantBit) != 0) _vacant -= 1 + else if (imbalanced) repack() + None + } + else { + val ans = Some(_values(i).asInstanceOf[V]) + _keys(i) = key + _values(i) = value.asInstanceOf[AnyRef] + ans + } + } + } + + /** Updates the map to include a new key-value pair. + * + * This is the fastest way to add an entry to a `LongMap`. + */ + override def update(key: Long, value: V): Unit = { + if (key == -key) { + if (key == 0) { + zeroValue = value.asInstanceOf[AnyRef] + extraKeys |= 1 + } + else { + minValue = value.asInstanceOf[AnyRef] + extraKeys |= 2 + } + } + else { + var i = seekEntryOrOpen(key) + if (i < 0) { + val j = i & IndexMask + _keys(j) = key + _values(j) = value.asInstanceOf[AnyRef] + _size += 1 + if ((i & VacantBit) != 0) _vacant -= 1 + else if (imbalanced) repack() + } + else { + _keys(i) = key + _values(i) = value.asInstanceOf[AnyRef] + } + } + } + + /** Adds a new key/value pair to this map and returns the map. */ + def +=(key: Long, value: V): this.type = { update(key, value); this } + + def +=(kv: (Long, V)): this.type = { update(kv._1, kv._2); this } + + def -=(key: Long): this.type = { + if (key == -key) { + if (key == 0L) { + extraKeys &= 0x2 + zeroValue = null + } + else { + extraKeys &= 0x1 + minValue = null + } + } + else { + val i = seekEntry(key) + if (i >= 0) { + _size -= 1 + _vacant += 1 + _keys(i) = Long.MinValue + _values(i) = null + } + } + this + } + + def iterator: Iterator[(Long, V)] = new Iterator[(Long, V)] { + private[this] val kz = _keys + private[this] val vz = _values + + private[this] var nextPair: (Long, V) = + if (extraKeys==0) null + else if ((extraKeys&1)==1) (0L, zeroValue.asInstanceOf[V]) + else (Long.MinValue, minValue.asInstanceOf[V]) + + private[this] var anotherPair: (Long, V) = + if (extraKeys==3) (Long.MinValue, minValue.asInstanceOf[V]) + else null + + private[this] var index = 0 + + def hasNext: Boolean = nextPair != null || (index < kz.length && { + var q = kz(index) + while (q == -q) { + index += 1 + if (index >= kz.length) return false + q = kz(index) + } + nextPair = (kz(index), vz(index).asInstanceOf[V]) + index += 1 + true + }) + def next = { + if (nextPair == null && !hasNext) throw new NoSuchElementException("next") + val ans = nextPair + if (anotherPair != null) { + nextPair = anotherPair + anotherPair = null + } + nextPair = null + ans + } + } + + override def foreach[A](f: ((Long,V)) => A) { + var i,j = 0 + while (i < _keys.length & j < _size) { + val k = _keys(i) + if (k != -k) { + j += 1 + f((k, _values(i).asInstanceOf[V])) + } + i += 1 + } + if ((extraKeys & 1) == 1) f((0L, zeroValue.asInstanceOf[V])) + if ((extraKeys & 2) == 2) f((Long.MinValue, minValue.asInstanceOf[V])) + } + + override def clone(): LongMap[V] = { + val kz = java.util.Arrays.copyOf(_keys, _keys.length) + val vz = java.util.Arrays.copyOf(_values, _values.length) + val lm = new LongMap[V](defaultEntry, 1, false) + lm.initializeTo(mask, extraKeys, zeroValue, minValue, _size, _vacant, kz, vz) + lm + } + + /** Applies a function to all keys of this map. */ + def foreachKey[A](f: Long => A) { + var i,j = 0 + while (i < _keys.length & j < _size) { + val k = _keys(i) + if (k != -k) { + j += 1 + f(k) + } + i += 1 + } + if ((extraKeys & 1) == 1) f(0L) + if ((extraKeys & 2) == 2) f(Long.MinValue) + } + + /** Applies a function to all values of this map. */ + def foreachValue[A](f: V => A) { + var i,j = 0 + while (i < _keys.length & j < _size) { + val k = _keys(i) + if (k != -k) { + j += 1 + f(_values(i).asInstanceOf[V]) + } + i += 1 + } + if ((extraKeys & 1) == 1) f(zeroValue.asInstanceOf[V]) + if ((extraKeys & 2) == 2) f(minValue.asInstanceOf[V]) + } + + /** Creates a new `LongMap` with different values. + * Unlike `mapValues`, this method generates a new + * collection immediately. + */ + def mapValuesNow[V1](f: V => V1): LongMap[V1] = { + val lm = new LongMap[V1](LongMap.exceptionDefault, 1, false) + val kz = java.util.Arrays.copyOf(_keys, _keys.length) + val vz = new Array[AnyRef](_values.length) + var i,j = 0 + while (i < _keys.length & j < _size) { + val k = _keys(i) + if (k != -k) { + j += 1 + vz(i) = f(_values(i).asInstanceOf[V]).asInstanceOf[AnyRef] + } + i += 1 + } + val zv = if ((extraKeys & 1) == 1) f(zeroValue.asInstanceOf[V]).asInstanceOf[AnyRef] else null + val mv = if ((extraKeys & 2) == 2) f(minValue.asInstanceOf[V]).asInstanceOf[AnyRef] else null + lm.initializeTo(mask, extraKeys, zv, mv, _size, _vacant, kz, vz) + lm + } + + /** Applies a transformation function to all values stored in this map. + * Note: the default, if any, is not transformed. + */ + def transformValues(f: V => V): this.type = { + var i,j = 0 + while (i < _keys.length & j < _size) { + val k = _keys(i) + if (k != -k) { + j += 1 + _values(i) = f(_values(i).asInstanceOf[V]).asInstanceOf[AnyRef] + } + i += 1 + } + if ((extraKeys & 1) == 1) zeroValue = f(zeroValue.asInstanceOf[V]).asInstanceOf[AnyRef] + if ((extraKeys & 2) == 2) minValue = f(minValue.asInstanceOf[V]).asInstanceOf[AnyRef] + this + } + + /* + override def toString = { + val sb = new StringBuilder("LongMap(") + var n = 0 + foreach{ case (k,v) => + if (n > 0) sb ++= ", " + sb ++= k.toString + sb ++= " -> " + sb ++= v.toString + n += 1 + } + sb += ')' + sb.result + } + */ +} + +object LongMap { + private final val IndexMask = 0x3FFFFFFF + private final val MissingBit = 0x80000000 + private final val VacantBit = 0x40000000 + private final val MissVacant = 0xC0000000 + + private val exceptionDefault: Long => Nothing = (k: Long) => throw new NoSuchElementException(k.toString) + + implicit def canBuildFrom[V, U]: CanBuildFrom[LongMap[V], (Long, U), LongMap[U]] = + new CanBuildFrom[LongMap[V], (Long, U), LongMap[U]] { + def apply(from: LongMap[V]): LongMapBuilder[U] = apply() + def apply(): LongMapBuilder[U] = new LongMapBuilder[U] + } + + final class LongMapBuilder[V] extends Builder[(Long, V), LongMap[V]] { + private[collection] var elems: LongMap[V] = new LongMap[V] + def +=(entry: (Long, V)): this.type = { + elems += entry + this + } + def clear() { elems = new LongMap[V] } + def result(): LongMap[V] = elems + } + + /** Creates a new `LongMap` with zero or more key/value pairs. */ + def apply[V](elems: (Long, V)*): LongMap[V] = { + val sz = if (elems.hasDefiniteSize) elems.size else 4 + val lm = new LongMap[V](sz * 2) + elems.foreach{ case (k,v) => lm(k) = v } + if (lm.size < (sz>>3)) lm.repack() + lm + } + + /** Creates a new empty `LongMap`. */ + def empty[V]: LongMap[V] = new LongMap[V] + + /** Creates a new empty `LongMap` with the supplied default */ + def withDefault[V](default: Long => V): LongMap[V] = new LongMap[V](default) + + /** Creates a new `LongMap` from arrays of keys and values. + * Equivalent to but more efficient than `LongMap((keys zip values): _*)`. + */ + def fromZip[V](keys: Array[Long], values: Array[V]): LongMap[V] = { + val sz = math.min(keys.length, values.length) + val lm = new LongMap[V](sz * 2) + var i = 0 + while (i < sz) { lm(keys(i)) = values(i); i += 1 } + if (lm.size < (sz>>3)) lm.repack() + lm + } + + /** Creates a new `LongMap` from keys and values. + * Equivalent to but more efficient than `LongMap((keys zip values): _*)`. + */ + def fromZip[V](keys: Iterable[Long], values: Iterable[V]): LongMap[V] = { + val sz = math.min(keys.size, values.size) + val lm = new LongMap[V](sz * 2) + val ki = keys.iterator + val vi = values.iterator + while (ki.hasNext && vi.hasNext) lm(ki.next) = vi.next + if (lm.size < (sz >> 3)) lm.repack() + lm + } +} diff --git a/src/library/scala/collection/mutable/Map.scala b/src/library/scala/collection/mutable/Map.scala index f72e1fc4e7..2ac3cb65b5 100644 --- a/src/library/scala/collection/mutable/Map.scala +++ b/src/library/scala/collection/mutable/Map.scala @@ -8,7 +8,8 @@ -package scala.collection +package scala +package collection package mutable import generic._ @@ -42,22 +43,10 @@ trait Map[A, B] * * Invoking transformer methods (e.g. `map`) will not preserve the default value. * - * @param d the function mapping keys to values, used for non-present keys + * @param d default value used for non-present keys * @return a wrapper of the map with a default value */ def withDefaultValue(d: B): mutable.Map[A, B] = new Map.WithDefault[A, B](this, x => d) - - /** Return a read-only projection of this map. !!! or just use an (immutable) MapProxy? - def readOnly : scala.collection.Map[A, B] = new scala.collection.Map[A, B] { - override def size = self.size - override def update(key: A, value: B) = self.update(key, value) - override def - (elem: A) = self - elem - override def iterator = self.iterator - override def foreach[U](f: ((A, B)) => U) = self.foreach(f) - override def empty[C] = self.empty[C] - def get(key: A) = self.get(key) - } - */ } /** $factoryInfo @@ -88,4 +77,4 @@ object Map extends MutableMapFactory[Map] { } /** Explicit instantiation of the `Map` trait to reduce class file size in subclasses. */ -private[scala] abstract class AbstractMap[A, B] extends scala.collection.AbstractMap[A, B] with Map[A, B] +abstract class AbstractMap[A, B] extends scala.collection.AbstractMap[A, B] with Map[A, B] diff --git a/src/library/scala/collection/mutable/MapBuilder.scala b/src/library/scala/collection/mutable/MapBuilder.scala index 8468e09e4d..a5a6b12ea9 100644 --- a/src/library/scala/collection/mutable/MapBuilder.scala +++ b/src/library/scala/collection/mutable/MapBuilder.scala @@ -7,7 +7,8 @@ \* */ -package scala.collection +package scala +package collection package mutable /** The canonical builder for immutable maps, working with the map's `+` method diff --git a/src/library/scala/collection/mutable/MapLike.scala b/src/library/scala/collection/mutable/MapLike.scala index 42e5a0a4c4..6230fc23aa 100644 --- a/src/library/scala/collection/mutable/MapLike.scala +++ b/src/library/scala/collection/mutable/MapLike.scala @@ -7,12 +7,13 @@ \* */ -package scala.collection +package scala +package collection package mutable import generic._ -import scala.annotation.{migration, bridge} -import parallel.mutable.ParMap +import scala.annotation.migration +import scala.collection.parallel.mutable.ParMap /** A template trait for mutable maps. * $mapNote @@ -50,8 +51,6 @@ trait MapLike[A, B, +This <: MapLike[A, B, This] with Map[A, B]] with Parallelizable[(A, B), ParMap[A, B]] { self => - import scala.collection.Traversable - /** A common implementation of `newBuilder` for all mutable maps * in terms of `empty`. * diff --git a/src/library/scala/collection/mutable/MapProxy.scala b/src/library/scala/collection/mutable/MapProxy.scala index c730e2b7c8..552cd9769b 100644 --- a/src/library/scala/collection/mutable/MapProxy.scala +++ b/src/library/scala/collection/mutable/MapProxy.scala @@ -6,7 +6,8 @@ ** |/ ** \* */ -package scala.collection +package scala +package collection package mutable /** @@ -19,6 +20,7 @@ package mutable * @version 2.0, 31/12/2006 * @since 1 */ +@deprecated("Proxying is deprecated due to lack of use and compiler-level support.", "2.11.0") trait MapProxy[A, B] extends Map[A, B] with MapProxyLike[A, B, Map[A, B]] { private def newProxy[B1 >: B](newSelf: Map[A, B1]): MapProxy[A, B1] = new MapProxy[A, B1] { val self = newSelf } diff --git a/src/library/scala/collection/mutable/MultiMap.scala b/src/library/scala/collection/mutable/MultiMap.scala index 4635bfbe64..78dfc35268 100644 --- a/src/library/scala/collection/mutable/MultiMap.scala +++ b/src/library/scala/collection/mutable/MultiMap.scala @@ -8,7 +8,8 @@ -package scala.collection +package scala +package collection package mutable diff --git a/src/library/scala/collection/mutable/MutableList.scala b/src/library/scala/collection/mutable/MutableList.scala index bc6272bfdb..a0d3ee0ef0 100644 --- a/src/library/scala/collection/mutable/MutableList.scala +++ b/src/library/scala/collection/mutable/MutableList.scala @@ -6,9 +6,8 @@ ** |/ ** \* */ - - -package scala.collection +package scala +package collection package mutable import generic._ @@ -61,8 +60,7 @@ extends AbstractSeq[A] tl } - // this method must be private for binary compatibility - private final def tailImpl(tl: MutableList[A]) { + protected final def tailImpl(tl: MutableList[A]) { require(nonEmpty, "tail of empty list") tl.first0 = first0.tail tl.len = len - 1 @@ -149,12 +147,10 @@ extends AbstractSeq[A] override def clone(): MutableList[A] = { val bf = newBuilder bf ++= seq - bf.result + bf.result() } - } - object MutableList extends SeqFactory[MutableList] { implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, MutableList[A]] = ReusableCBF.asInstanceOf[GenericCanBuildFrom[A]] diff --git a/src/library/scala/collection/mutable/ObservableBuffer.scala b/src/library/scala/collection/mutable/ObservableBuffer.scala index bcaf977727..9c3247f83b 100644 --- a/src/library/scala/collection/mutable/ObservableBuffer.scala +++ b/src/library/scala/collection/mutable/ObservableBuffer.scala @@ -8,7 +8,8 @@ -package scala.collection +package scala +package collection package mutable import script._ @@ -22,6 +23,7 @@ import script._ * @version 1.0, 08/07/2003 * @since 1 */ +@deprecated("Observables are deprecated because scripting is deprecated.", "2.11.0") trait ObservableBuffer[A] extends Buffer[A] with Publisher[Message[A] with Undoable] { type Pub <: ObservableBuffer[A] @@ -65,7 +67,7 @@ trait ObservableBuffer[A] extends Buffer[A] with Publisher[Message[A] with Undoa } abstract override def clear(): Unit = { - super.clear + super.clear() publish(new Reset with Undoable { def undo() { throw new UnsupportedOperationException("cannot undo") } }) diff --git a/src/library/scala/collection/mutable/ObservableMap.scala b/src/library/scala/collection/mutable/ObservableMap.scala index d81c90bf4c..7509b72568 100644 --- a/src/library/scala/collection/mutable/ObservableMap.scala +++ b/src/library/scala/collection/mutable/ObservableMap.scala @@ -8,7 +8,8 @@ -package scala.collection +package scala +package collection package mutable import script._ @@ -24,6 +25,7 @@ import script._ * @version 2.0, 31/12/2006 * @since 1 */ +@deprecated("Observables are deprecated because scripting is deprecated.", "2.11.0") trait ObservableMap[A, B] extends Map[A, B] with Publisher[Message[(A, B)] with Undoable] { @@ -60,7 +62,7 @@ trait ObservableMap[A, B] extends Map[A, B] with Publisher[Message[(A, B)] with } abstract override def clear(): Unit = { - super.clear + super.clear() publish(new Reset with Undoable { def undo(): Unit = throw new UnsupportedOperationException("cannot undo") }) diff --git a/src/library/scala/collection/mutable/ObservableSet.scala b/src/library/scala/collection/mutable/ObservableSet.scala index 3e79506413..19b4a5e39f 100644 --- a/src/library/scala/collection/mutable/ObservableSet.scala +++ b/src/library/scala/collection/mutable/ObservableSet.scala @@ -8,7 +8,8 @@ -package scala.collection +package scala +package collection package mutable import script._ @@ -22,6 +23,7 @@ import script._ * @version 1.0, 08/07/2003 * @since 1 */ +@deprecated("Observables are deprecated because scripting is deprecated.", "2.11.0") trait ObservableSet[A] extends Set[A] with Publisher[Message[A] with Undoable] { @@ -44,7 +46,7 @@ trait ObservableSet[A] extends Set[A] with Publisher[Message[A] with Undoable] } abstract override def clear(): Unit = { - super.clear + super.clear() publish(new Reset with Undoable { def undo(): Unit = throw new UnsupportedOperationException("cannot undo") }) diff --git a/src/library/scala/collection/mutable/OpenHashMap.scala b/src/library/scala/collection/mutable/OpenHashMap.scala index 8b3e52470a..aade2ed6fb 100644 --- a/src/library/scala/collection/mutable/OpenHashMap.scala +++ b/src/library/scala/collection/mutable/OpenHashMap.scala @@ -17,7 +17,6 @@ package mutable * @since 2.7 */ object OpenHashMap { - import generic.BitOperations.Int.highestOneBit def apply[K, V](elems : (K, V)*) = new OpenHashMap[K, V] ++= elems def empty[K, V] = new OpenHashMap[K, V] @@ -27,7 +26,7 @@ object OpenHashMap { var value: Option[Value]) extends HashEntry[Key, OpenEntry[Key, Value]] - private[mutable] def nextPowerOfTwo(i : Int) = highestOneBit(i) << 1; + private[mutable] def nextPositivePowerOfTwo(i : Int) = 1 << (32 - Integer.numberOfLeadingZeros(i - 1)) } /** A mutable hash map based on an open hashing scheme. The precise scheme is @@ -62,7 +61,7 @@ extends AbstractMap[Key, Value] override def empty: OpenHashMap[Key, Value] = OpenHashMap.empty[Key, Value] - private[this] val actualInitialSize = OpenHashMap.nextPowerOfTwo(initialSize) + private[this] val actualInitialSize = OpenHashMap.nextPositivePowerOfTwo(initialSize) private var mask = actualInitialSize - 1 private var table : Array[Entry] = new Array[Entry](actualInitialSize) @@ -78,8 +77,8 @@ extends AbstractMap[Key, Value] /** Returns a mangled hash code of the provided key. */ protected def hashOf(key: Key) = { var h = key.## - h ^= ((h >>> 20) ^ (h >>> 12)); - h ^ (h >>> 7) ^ (h >>> 4); + h ^= ((h >>> 20) ^ (h >>> 12)) + h ^ (h >>> 7) ^ (h >>> 4) } private[this] def growTable() = { @@ -89,7 +88,7 @@ extends AbstractMap[Key, Value] table = new Array[Entry](newSize) mask = newSize - 1 oldTable.foreach( entry => - if (entry != null && entry.value != None) addEntry(entry)); + if (entry != null && entry.value != None) addEntry(entry)) deleted = 0 } @@ -117,25 +116,28 @@ extends AbstractMap[Key, Value] put(key, hashOf(key), value) } + @deprecatedOverriding("+= should not be overridden in order to maintain consistency with put.", "2.11.0") def += (kv: (Key, Value)): this.type = { put(kv._1, kv._2); this } + + @deprecatedOverriding("-= should not be overridden in order to maintain consistency with remove.", "2.11.0") def -= (key: Key): this.type = { remove(key); this } override def put(key: Key, value: Value): Option[Value] = put(key, hashOf(key), value) private def put(key: Key, hash: Int, value: Value): Option[Value] = { - if (2 * (size + deleted) > mask) growTable + if (2 * (size + deleted) > mask) growTable() val index = findIndex(key, hash) val entry = table(index) if (entry == null) { - table(index) = new OpenEntry(key, hash, Some(value)); + table(index) = new OpenEntry(key, hash, Some(value)) modCount += 1 size += 1 None } else { val res = entry.value if (entry.value == None) { size += 1; modCount += 1 } - entry.value = Some(value); + entry.value = Some(value) res } } @@ -161,13 +163,13 @@ extends AbstractMap[Key, Value] while(entry != null){ if (entry.hash == hash && entry.key == key){ - return entry.value; + return entry.value } - j = 5 * j + 1 + perturb; - perturb >>= 5; - index = j & mask; - entry = table(index); + j = 5 * j + 1 + perturb + perturb >>= 5 + index = j & mask + entry = table(index) } None } @@ -182,8 +184,8 @@ extends AbstractMap[Key, Value] val initialModCount = modCount private[this] def advance() { - if (initialModCount != modCount) sys.error("Concurrent modification"); - while((index <= mask) && (table(index) == null || table(index).value == None)) index+=1; + if (initialModCount != modCount) sys.error("Concurrent modification") + while((index <= mask) && (table(index) == null || table(index).value == None)) index+=1 } def hasNext = {advance(); index <= mask } @@ -198,7 +200,7 @@ extends AbstractMap[Key, Value] override def clone() = { val it = new OpenHashMap[Key, Value] - foreachUndeletedEntry(entry => it.put(entry.key, entry.hash, entry.value.get)); + foreachUndeletedEntry(entry => it.put(entry.key, entry.hash, entry.value.get)) it } @@ -213,24 +215,24 @@ extends AbstractMap[Key, Value] * @param f The function to apply to each key, value mapping. */ override def foreach[U](f : ((Key, Value)) => U) { - val startModCount = modCount; + val startModCount = modCount foreachUndeletedEntry(entry => { if (modCount != startModCount) sys.error("Concurrent Modification") f((entry.key, entry.value.get))} - ); + ) } private[this] def foreachUndeletedEntry(f : Entry => Unit){ - table.foreach(entry => if (entry != null && entry.value != None) f(entry)); + table.foreach(entry => if (entry != null && entry.value != None) f(entry)) } override def transform(f : (Key, Value) => Value) = { - foreachUndeletedEntry(entry => entry.value = Some(f(entry.key, entry.value.get))); + foreachUndeletedEntry(entry => entry.value = Some(f(entry.key, entry.value.get))) this } override def retain(f : (Key, Value) => Boolean) = { - foreachUndeletedEntry(entry => if (!f(entry.key, entry.value.get)) {entry.value = None; size -= 1; deleted += 1} ); + foreachUndeletedEntry(entry => if (!f(entry.key, entry.value.get)) {entry.value = None; size -= 1; deleted += 1} ) this } diff --git a/src/library/scala/collection/mutable/PriorityQueue.scala b/src/library/scala/collection/mutable/PriorityQueue.scala index 84257c6e97..b949bec48a 100644 --- a/src/library/scala/collection/mutable/PriorityQueue.scala +++ b/src/library/scala/collection/mutable/PriorityQueue.scala @@ -6,9 +6,8 @@ ** |/ ** \* */ - - -package scala.collection +package scala +package collection package mutable import generic._ @@ -31,6 +30,7 @@ import generic._ * @define mayNotTerminateInf * @define willNotTerminateInf */ +@deprecatedInheritance("PriorityQueue is not intended to be subclassed due to extensive private implementation details.", "2.11.0") class PriorityQueue[A](implicit val ord: Ordering[A]) extends AbstractIterable[A] with Iterable[A] @@ -43,7 +43,7 @@ class PriorityQueue[A](implicit val ord: Ordering[A]) { import ord._ - private class ResizableArrayAccess[A] extends AbstractSeq[A] with ResizableArray[A] { + private class ResizableArrayAccess[A] extends AbstractSeq[A] with ResizableArray[A] with Serializable { def p_size0 = size0 def p_size0_=(s: Int) = size0 = s def p_array = array @@ -134,11 +134,11 @@ class PriorityQueue[A](implicit val ord: Ordering[A]) throw new NoSuchElementException("no element to remove from heap") def dequeueAll[A1 >: A, That](implicit bf: CanBuildFrom[_, A1, That]): That = { - val b = bf.apply + val b = bf.apply() while (nonEmpty) { b += dequeue() } - b.result + b.result() } /** Returns the element with the highest priority in the queue, @@ -146,14 +146,6 @@ class PriorityQueue[A](implicit val ord: Ordering[A]) * * @return the element with the highest priority. */ - @deprecated("Use `head` instead.", "2.9.0") - def max: A = if (resarr.p_size0 > 1) toA(resarr.p_array(1)) else throw new NoSuchElementException("queue is empty") - - /** Returns the element with the highest priority in the queue, - * or throws an error if there is no element contained in the queue. - * - * @return the element with the highest priority. - */ override def head: A = if (resarr.p_size0 > 1) toA(resarr.p_array(1)) else throw new NoSuchElementException("queue is empty") /** Removes all elements from the queue. After this operation is completed, diff --git a/src/library/scala/collection/mutable/PriorityQueueProxy.scala b/src/library/scala/collection/mutable/PriorityQueueProxy.scala index 3bb5d32cf8..b24551a6b7 100644 --- a/src/library/scala/collection/mutable/PriorityQueueProxy.scala +++ b/src/library/scala/collection/mutable/PriorityQueueProxy.scala @@ -7,7 +7,8 @@ \* */ -package scala.collection +package scala +package collection package mutable /** This class servers as a proxy for priority queues. The @@ -18,6 +19,7 @@ package mutable * @version 1.0, 03/05/2004 * @since 1 */ +@deprecated("Proxying is deprecated due to lack of use and compiler-level support.", "2.11.0") abstract class PriorityQueueProxy[A](implicit ord: Ordering[A]) extends PriorityQueue[A] with Proxy { @@ -66,7 +68,7 @@ abstract class PriorityQueueProxy[A](implicit ord: Ordering[A]) extends Priority * * @return the element with the highest priority. */ - override def dequeue(): A = self.dequeue + override def dequeue(): A = self.dequeue() /** Returns the element with the highest priority in the queue, * or throws an error if there is no element contained in the queue. @@ -75,18 +77,10 @@ abstract class PriorityQueueProxy[A](implicit ord: Ordering[A]) extends Priority */ override def head: A = self.head - /** Returns the element with the highest priority in the queue, - * or throws an error if there is no element contained in the queue. - * - * @return the element with the highest priority. - */ - @deprecated("Use `head` instead.", "2.9.0") - override def max: A = self.max - /** Removes all elements from the queue. After this operation is completed, * the queue will be empty. */ - override def clear(): Unit = self.clear + override def clear(): Unit = self.clear() /** Returns a regular queue containing the same elements. */ diff --git a/src/library/scala/collection/mutable/Publisher.scala b/src/library/scala/collection/mutable/Publisher.scala index e31205b477..22bbea16ef 100644 --- a/src/library/scala/collection/mutable/Publisher.scala +++ b/src/library/scala/collection/mutable/Publisher.scala @@ -8,7 +8,8 @@ -package scala.collection +package scala +package collection package mutable @@ -45,7 +46,7 @@ trait Publisher[Evt] { def suspendSubscription(sub: Sub) { suspended += sub } def activateSubscription(sub: Sub) { suspended -= sub } def removeSubscription(sub: Sub) { filters -= sub } - def removeSubscriptions() { filters.clear } + def removeSubscriptions() { filters.clear() } protected def publish(event: Evt) { filters.keys.foreach(sub => diff --git a/src/library/scala/collection/mutable/Queue.scala b/src/library/scala/collection/mutable/Queue.scala index 8ef5f6aeb7..7c890fe309 100644 --- a/src/library/scala/collection/mutable/Queue.scala +++ b/src/library/scala/collection/mutable/Queue.scala @@ -8,7 +8,8 @@ -package scala.collection +package scala +package collection package mutable import generic._ @@ -142,6 +143,7 @@ extends MutableList[A] /** Return the proper suffix of this list which starts with the first element that satisfies `p`. * That element is unlinked from the list. If no element satisfies `p`, return None. */ + @deprecated("extractFirst inappropriately exposes implementation details. Use dequeue or dequeueAll.", "2.11.0") def extractFirst(start: LinkedList[A], p: A => Boolean): Option[LinkedList[A]] = { if (isEmpty) None else { @@ -167,13 +169,6 @@ extends MutableList[A] */ def front: A = head - // this method (duplicated from MutableList) must be private for binary compatibility - private final def tailImpl(tl: Queue[A]) { - require(nonEmpty, "tail of empty list") - tl.first0 = first0.tail - tl.len = len - 1 - tl.last0 = if (tl.len == 0) tl.first0 else last0 - } // TODO - Don't override this just for new to create appropriate type.... override def tail: Queue[A] = { @@ -185,7 +180,7 @@ extends MutableList[A] override def clone(): Queue[A] = { val bf = newBuilder bf ++= seq - bf.result + bf.result() } private[this] def decrementLength() { diff --git a/src/library/scala/collection/mutable/QueueProxy.scala b/src/library/scala/collection/mutable/QueueProxy.scala index c286a340e3..22ff3306d5 100644 --- a/src/library/scala/collection/mutable/QueueProxy.scala +++ b/src/library/scala/collection/mutable/QueueProxy.scala @@ -8,7 +8,8 @@ -package scala.collection +package scala +package collection package mutable /** `Queue` objects implement data structures that allow to @@ -20,6 +21,7 @@ package mutable * @version 1.1, 03/05/2004 * @since 1 */ +@deprecated("Proxying is deprecated due to lack of use and compiler-level support.", "2.11.0") trait QueueProxy[A] extends Queue[A] with Proxy { def self: Queue[A] @@ -67,7 +69,7 @@ trait QueueProxy[A] extends Queue[A] with Proxy { * * @return the first element of the queue. */ - override def dequeue(): A = self.dequeue + override def dequeue(): A = self.dequeue() /** Returns the first element in the queue, or throws an error if there * is no element contained in the queue. @@ -79,7 +81,7 @@ trait QueueProxy[A] extends Queue[A] with Proxy { /** Removes all elements from the queue. After this operation is completed, * the queue will be empty. */ - override def clear(): Unit = self.clear + override def clear(): Unit = self.clear() /** Returns an iterator over all elements on the queue. * diff --git a/src/library/scala/collection/mutable/ResizableArray.scala b/src/library/scala/collection/mutable/ResizableArray.scala index 4a12f9588c..c3047522e2 100644 --- a/src/library/scala/collection/mutable/ResizableArray.scala +++ b/src/library/scala/collection/mutable/ResizableArray.scala @@ -89,16 +89,20 @@ trait ResizableArray[A] extends IndexedSeq[A] } } - /** Ensure that the internal array has at `n` cells. */ + /** Ensure that the internal array has at least `n` cells. */ protected def ensureSize(n: Int) { - if (n > array.length) { - var newsize = array.length * 2 - while (n > newsize) - newsize = newsize * 2 - - val newar: Array[AnyRef] = new Array(newsize) - scala.compat.Platform.arraycopy(array, 0, newar, 0, size0) - array = newar + // Use a Long to prevent overflows + val arrayLength: Long = array.length + if (n > arrayLength) { + var newSize: Long = arrayLength * 2 + while (n > newSize) + newSize = newSize * 2 + // Clamp newSize to Int.MaxValue + if (newSize > Int.MaxValue) newSize = Int.MaxValue + + val newArray: Array[AnyRef] = new Array(newSize.toInt) + scala.compat.Platform.arraycopy(array, 0, newArray, 0, size0) + array = newArray } } diff --git a/src/library/scala/collection/mutable/RevertibleHistory.scala b/src/library/scala/collection/mutable/RevertibleHistory.scala index 5544a21a55..725a8113ec 100644 --- a/src/library/scala/collection/mutable/RevertibleHistory.scala +++ b/src/library/scala/collection/mutable/RevertibleHistory.scala @@ -8,7 +8,8 @@ -package scala.collection +package scala +package collection package mutable @@ -30,7 +31,7 @@ class RevertibleHistory[Evt <: Undoable, Pub] extends History[Evt, Pub] with Und */ def undo(): Unit = { val old = log.toList.reverse - clear - old.foreach { case (sub, event) => event.undo } + clear() + old.foreach { case (sub, event) => event.undo() } } } diff --git a/src/library/scala/collection/mutable/Seq.scala b/src/library/scala/collection/mutable/Seq.scala index 9d9399ebb4..eafde70a2d 100644 --- a/src/library/scala/collection/mutable/Seq.scala +++ b/src/library/scala/collection/mutable/Seq.scala @@ -8,7 +8,8 @@ -package scala.collection +package scala +package collection package mutable import generic._ @@ -44,4 +45,4 @@ object Seq extends SeqFactory[Seq] { } /** Explicit instantiation of the `Seq` trait to reduce class file size in subclasses. */ -private[scala] abstract class AbstractSeq[A] extends scala.collection.AbstractSeq[A] with Seq[A] +abstract class AbstractSeq[A] extends scala.collection.AbstractSeq[A] with Seq[A] diff --git a/src/library/scala/collection/mutable/SeqLike.scala b/src/library/scala/collection/mutable/SeqLike.scala index 447100cf4c..6987066f2b 100644 --- a/src/library/scala/collection/mutable/SeqLike.scala +++ b/src/library/scala/collection/mutable/SeqLike.scala @@ -6,10 +6,10 @@ ** |/ ** \* */ -package scala.collection +package scala +package collection package mutable -import generic._ import parallel.mutable.ParSeq /** A template trait for mutable sequences of type `mutable.Seq[A]`. diff --git a/src/library/scala/collection/mutable/Set.scala b/src/library/scala/collection/mutable/Set.scala index 023ff63056..97574718e8 100644 --- a/src/library/scala/collection/mutable/Set.scala +++ b/src/library/scala/collection/mutable/Set.scala @@ -8,7 +8,8 @@ -package scala.collection +package scala +package collection package mutable import generic._ @@ -42,4 +43,4 @@ object Set extends MutableSetFactory[Set] { } /** Explicit instantiation of the `Set` trait to reduce class file size in subclasses. */ -private[scala] abstract class AbstractSet[A] extends AbstractIterable[A] with Set[A] +abstract class AbstractSet[A] extends AbstractIterable[A] with Set[A] diff --git a/src/library/scala/collection/mutable/SetBuilder.scala b/src/library/scala/collection/mutable/SetBuilder.scala index 42fd651d41..01bfdc96ed 100644 --- a/src/library/scala/collection/mutable/SetBuilder.scala +++ b/src/library/scala/collection/mutable/SetBuilder.scala @@ -6,12 +6,10 @@ ** |/ ** \* */ - -package scala.collection +package scala +package collection package mutable -import generic._ - /** The canonical builder for mutable Sets. * * @tparam A The type of the elements that will be contained in this set. diff --git a/src/library/scala/collection/mutable/SetLike.scala b/src/library/scala/collection/mutable/SetLike.scala index 71da4c89dc..d749167870 100644 --- a/src/library/scala/collection/mutable/SetLike.scala +++ b/src/library/scala/collection/mutable/SetLike.scala @@ -6,12 +6,13 @@ ** |/ ** \* */ -package scala.collection +package scala +package collection package mutable import generic._ import script._ -import scala.annotation.{ migration, bridge } +import scala.annotation.migration import parallel.mutable.ParSet /** A template trait for mutable sets of type `mutable.Set[A]`. @@ -209,11 +210,12 @@ trait SetLike[A, +This <: SetLike[A, This] with Set[A]] * @throws `Predef.UnsupportedOperationException` * if the message was not understood. */ - def <<(cmd: Message[A]): Unit = cmd match { - case Include(_, x) => this += x - case Remove(_, x) => this -= x - case Reset() => clear - case s: Script[_] => s.iterator foreach << - case _ => throw new UnsupportedOperationException("message " + cmd + " not understood") - } + @deprecated("Scripting is deprecated.", "2.11.0") + def <<(cmd: Message[A]): Unit = cmd match { + case Include(_, x) => this += x + case Remove(_, x) => this -= x + case Reset() => clear() + case s: Script[_] => s.iterator foreach << + case _ => throw new UnsupportedOperationException("message " + cmd + " not understood") + } } diff --git a/src/library/scala/collection/mutable/SetProxy.scala b/src/library/scala/collection/mutable/SetProxy.scala index c9f297509f..74279507ff 100644 --- a/src/library/scala/collection/mutable/SetProxy.scala +++ b/src/library/scala/collection/mutable/SetProxy.scala @@ -6,7 +6,8 @@ ** |/ ** \* */ -package scala.collection +package scala +package collection package mutable /** This is a simple wrapper class for [[scala.collection.mutable.Set]]. @@ -17,6 +18,7 @@ package mutable * @version 1.1, 09/05/2004 * @since 1 */ +@deprecated("Proxying is deprecated due to lack of use and compiler-level support.", "2.11.0") trait SetProxy[A] extends Set[A] with SetProxyLike[A, Set[A]] { override def repr = this override def empty = new SetProxy[A] { val self = SetProxy.this.self.empty } diff --git a/src/library/scala/collection/mutable/SortedSet.scala b/src/library/scala/collection/mutable/SortedSet.scala index 41f2c6e39f..0f2fa75abd 100644 --- a/src/library/scala/collection/mutable/SortedSet.scala +++ b/src/library/scala/collection/mutable/SortedSet.scala @@ -6,7 +6,8 @@ ** |/ ** \* */ -package scala.collection +package scala +package collection package mutable import generic._ diff --git a/src/library/scala/collection/mutable/Stack.scala b/src/library/scala/collection/mutable/Stack.scala index 6eef250f9d..53b6c59939 100644 --- a/src/library/scala/collection/mutable/Stack.scala +++ b/src/library/scala/collection/mutable/Stack.scala @@ -8,7 +8,8 @@ -package scala.collection +package scala +package collection package mutable import generic._ @@ -118,7 +119,7 @@ extends AbstractSeq[A] * @param xs the traversable object. * @return the stack with the new elements on top. */ - def pushAll(xs: TraversableOnce[A]): this.type = { xs.seq foreach push ; this } + def pushAll(xs: TraversableOnce[A]): this.type = { xs foreach push ; this } /** Returns the top element of the stack. This method will not remove * the element from the stack. An error is signaled if there is no diff --git a/src/library/scala/collection/mutable/StackProxy.scala b/src/library/scala/collection/mutable/StackProxy.scala index 16f13ff42c..81e63b05d2 100644 --- a/src/library/scala/collection/mutable/StackProxy.scala +++ b/src/library/scala/collection/mutable/StackProxy.scala @@ -6,7 +6,8 @@ ** |/ ** \* */ -package scala.collection +package scala +package collection package mutable /** A stack implements a data structure which allows to store and retrieve @@ -18,6 +19,7 @@ package mutable * @version 1.0, 10/05/2004 * @since 1 */ +@deprecated("Proxying is deprecated due to lack of use and compiler-level support.", "2.11.0") trait StackProxy[A] extends Stack[A] with Proxy { def self: Stack[A] @@ -58,7 +60,7 @@ trait StackProxy[A] extends Stack[A] with Proxy { self.push(elem) this } - + /** Returns the top element of the stack. This method will not remove * the element from the stack. An error is signaled if there is no * element on the stack. @@ -69,13 +71,13 @@ trait StackProxy[A] extends Stack[A] with Proxy { /** Removes the top element from the stack. */ - override def pop(): A = self.pop + override def pop(): A = self.pop() /** * Removes all elements from the stack. After this operation completed, * the stack will be empty. */ - override def clear(): Unit = self.clear + override def clear(): Unit = self.clear() /** Returns an iterator over all elements on the stack. This iterator * is stable with respect to state changes in the stack object; i.e. diff --git a/src/library/scala/collection/mutable/StringBuilder.scala b/src/library/scala/collection/mutable/StringBuilder.scala index 4d269a95b1..498e9e461e 100644 --- a/src/library/scala/collection/mutable/StringBuilder.scala +++ b/src/library/scala/collection/mutable/StringBuilder.scala @@ -6,7 +6,8 @@ ** |/ ** \* */ -package scala.collection +package scala +package collection package mutable import java.lang.{ StringBuilder => JavaStringBuilder } @@ -255,8 +256,8 @@ final class StringBuilder(private val underlying: JavaStringBuilder) * @return This StringBuilder. */ def append(x: Boolean): StringBuilder = { underlying append x ; this } - def append(x: Byte): StringBuilder = { underlying append x ; this } - def append(x: Short): StringBuilder = { underlying append x ; this } + def append(x: Byte): StringBuilder = append(x.toInt) + def append(x: Short): StringBuilder = append(x.toInt) def append(x: Int): StringBuilder = { underlying append x ; this } def append(x: Long): StringBuilder = { underlying append x ; this } def append(x: Float): StringBuilder = { underlying append x ; this } @@ -359,8 +360,8 @@ final class StringBuilder(private val underlying: JavaStringBuilder) * @return this StringBuilder. */ def insert(index: Int, x: Boolean): StringBuilder = insert(index, String.valueOf(x)) - def insert(index: Int, x: Byte): StringBuilder = insert(index, String.valueOf(x)) - def insert(index: Int, x: Short): StringBuilder = insert(index, String.valueOf(x)) + def insert(index: Int, x: Byte): StringBuilder = insert(index, x.toInt) + def insert(index: Int, x: Short): StringBuilder = insert(index, x.toInt) def insert(index: Int, x: Int): StringBuilder = insert(index, String.valueOf(x)) def insert(index: Int, x: Long): StringBuilder = insert(index, String.valueOf(x)) def insert(index: Int, x: Float): StringBuilder = insert(index, String.valueOf(x)) diff --git a/src/library/scala/collection/mutable/Subscriber.scala b/src/library/scala/collection/mutable/Subscriber.scala index 35d31d7316..c2aa9be72d 100644 --- a/src/library/scala/collection/mutable/Subscriber.scala +++ b/src/library/scala/collection/mutable/Subscriber.scala @@ -6,7 +6,8 @@ ** |/ ** \* */ -package scala.collection +package scala +package collection package mutable /** `Subscriber[A, B]` objects may subscribe to events of type `A` diff --git a/src/library/scala/collection/mutable/SynchronizedBuffer.scala b/src/library/scala/collection/mutable/SynchronizedBuffer.scala index bf9a70c5b7..8c646b0ce5 100644 --- a/src/library/scala/collection/mutable/SynchronizedBuffer.scala +++ b/src/library/scala/collection/mutable/SynchronizedBuffer.scala @@ -8,7 +8,8 @@ -package scala.collection +package scala +package collection package mutable import script._ @@ -24,6 +25,7 @@ import script._ * @define Coll `SynchronizedBuffer` * @define coll synchronized buffer */ +@deprecated("Synchronization via traits is deprecated as it is inherently unreliable. Consider java.util.concurrent.ConcurrentLinkedQueue as an alternative.", "2.11.0") trait SynchronizedBuffer[A] extends Buffer[A] { import scala.collection.Traversable @@ -157,9 +159,10 @@ trait SynchronizedBuffer[A] extends Buffer[A] { /** Clears the buffer contents. */ abstract override def clear(): Unit = synchronized { - super.clear + super.clear() } + @deprecated("Scripting is deprecated.", "2.11.0") override def <<(cmd: Message[A]): Unit = synchronized { super.<<(cmd) } diff --git a/src/library/scala/collection/mutable/SynchronizedMap.scala b/src/library/scala/collection/mutable/SynchronizedMap.scala index 5a3562cb22..9876296ebe 100644 --- a/src/library/scala/collection/mutable/SynchronizedMap.scala +++ b/src/library/scala/collection/mutable/SynchronizedMap.scala @@ -6,9 +6,8 @@ ** |/ ** \* */ - - -package scala.collection +package scala +package collection package mutable import scala.annotation.migration @@ -25,6 +24,7 @@ import scala.annotation.migration * @define Coll `SynchronizedMap` * @define coll synchronized map */ +@deprecated("Synchronization via traits is deprecated as it is inherently unreliable. Consider java.util.concurrent.ConcurrentHashMap as an alternative.", "2.11.0") trait SynchronizedMap[A, B] extends Map[A, B] { abstract override def get(key: A): Option[B] = synchronized { super.get(key) } diff --git a/src/library/scala/collection/mutable/SynchronizedPriorityQueue.scala b/src/library/scala/collection/mutable/SynchronizedPriorityQueue.scala index 8dfc40b9c8..d3c0b85f69 100644 --- a/src/library/scala/collection/mutable/SynchronizedPriorityQueue.scala +++ b/src/library/scala/collection/mutable/SynchronizedPriorityQueue.scala @@ -8,7 +8,8 @@ -package scala.collection +package scala +package collection package mutable /** This class implements synchronized priority queues using a binary heap. @@ -23,6 +24,7 @@ package mutable * @define Coll `SynchronizedPriorityQueue` * @define coll synchronized priority queue */ +@deprecated("Comprehensive synchronization via selective overriding of methods is inherently unreliable. Consider java.util.concurrent.ConcurrentSkipListSet as an alternative.", "2.11.0") class SynchronizedPriorityQueue[A](implicit ord: Ordering[A]) extends PriorityQueue[A] { /** Checks if the queue is empty. @@ -64,7 +66,7 @@ class SynchronizedPriorityQueue[A](implicit ord: Ordering[A]) extends PriorityQu * * @return the element with the highest priority. */ - override def dequeue(): A = synchronized { super.dequeue } + override def dequeue(): A = synchronized { super.dequeue() } /** Returns the element with the highest priority in the queue, * or throws an error if there is no element contained in the queue. @@ -73,18 +75,10 @@ class SynchronizedPriorityQueue[A](implicit ord: Ordering[A]) extends PriorityQu */ override def head: A = synchronized { super.head } - /** Returns the element with the highest priority in the queue, - * or throws an error if there is no element contained in the queue. - * - * @return the element with the highest priority. - */ - @deprecated("Use `head` instead.", "2.9.0") - override def max: A = synchronized { super.max } - /** Removes all elements from the queue. After this operation is completed, * the queue will be empty. */ - override def clear(): Unit = synchronized { super.clear } + override def clear(): Unit = synchronized { super.clear() } /** Returns an iterator which yield all the elements of the priority * queue in descending priority order. diff --git a/src/library/scala/collection/mutable/SynchronizedQueue.scala b/src/library/scala/collection/mutable/SynchronizedQueue.scala index 9559d5eaa5..48e40ab27f 100644 --- a/src/library/scala/collection/mutable/SynchronizedQueue.scala +++ b/src/library/scala/collection/mutable/SynchronizedQueue.scala @@ -8,7 +8,8 @@ -package scala.collection +package scala +package collection package mutable @@ -24,9 +25,8 @@ package mutable * @define Coll `SynchronizedQueue` * @define coll synchronized queue */ +@deprecated("Synchronization via selective overriding of methods is inherently unreliable. Consider java.util.concurrent.ConcurrentLinkedQueue as an alternative.", "2.11.0") class SynchronizedQueue[A] extends Queue[A] { - import scala.collection.Traversable - /** Checks if the queue is empty. * * @return true, iff there is no element in the queue. @@ -58,7 +58,7 @@ class SynchronizedQueue[A] extends Queue[A] { * * @return the first element of the queue. */ - override def dequeue(): A = synchronized { super.dequeue } + override def dequeue(): A = synchronized { super.dequeue() } /** Returns the first element in the queue which satisfies the * given predicate, and removes this element from the queue. @@ -87,7 +87,7 @@ class SynchronizedQueue[A] extends Queue[A] { /** Removes all elements from the queue. After this operation is completed, * the queue will be empty. */ - override def clear(): Unit = synchronized { super.clear } + override def clear(): Unit = synchronized { super.clear() } /** Checks if two queues are structurally identical. * diff --git a/src/library/scala/collection/mutable/SynchronizedSet.scala b/src/library/scala/collection/mutable/SynchronizedSet.scala index e4a44993ff..60e2e79d3f 100644 --- a/src/library/scala/collection/mutable/SynchronizedSet.scala +++ b/src/library/scala/collection/mutable/SynchronizedSet.scala @@ -7,7 +7,8 @@ \* */ -package scala.collection +package scala +package collection package mutable import script._ @@ -23,9 +24,8 @@ import script._ * @define Coll `SynchronizedSet` * @define coll synchronized set */ +@deprecated("Synchronization via traits is deprecated as it is inherently unreliable. Consider java.util.concurrent.ConcurrentHashMap[A,Unit] as an alternative.", "2.11.0") trait SynchronizedSet[A] extends Set[A] { - import scala.collection.Traversable - abstract override def size: Int = synchronized { super.size } @@ -71,7 +71,7 @@ trait SynchronizedSet[A] extends Set[A] { } abstract override def clear(): Unit = synchronized { - super.clear + super.clear() } override def subsetOf(that: scala.collection.GenSet[A]) = synchronized { @@ -94,6 +94,7 @@ trait SynchronizedSet[A] extends Set[A] { super.toString } + @deprecated("Scripting is deprecated.", "2.11.0") override def <<(cmd: Message[A]): Unit = synchronized { super.<<(cmd) } diff --git a/src/library/scala/collection/mutable/SynchronizedStack.scala b/src/library/scala/collection/mutable/SynchronizedStack.scala index 5d7c9f6073..bbb6f5a9bb 100644 --- a/src/library/scala/collection/mutable/SynchronizedStack.scala +++ b/src/library/scala/collection/mutable/SynchronizedStack.scala @@ -8,7 +8,8 @@ -package scala.collection +package scala +package collection package mutable @@ -24,6 +25,7 @@ package mutable * @define Coll `SynchronizedStack` * @define coll synchronized stack */ +@deprecated("Synchronization via selective overriding of methods is inherently unreliable. Consider java.util.concurrent.LinkedBlockingDequeue instead.", "2.11.0") class SynchronizedStack[A] extends Stack[A] { import scala.collection.Traversable @@ -67,13 +69,13 @@ class SynchronizedStack[A] extends Stack[A] { /** Removes the top element from the stack. */ - override def pop(): A = synchronized { super.pop } + override def pop(): A = synchronized { super.pop() } /** * Removes all elements from the stack. After this operation completed, * the stack will be empty. */ - override def clear(): Unit = synchronized { super.clear } + override def clear(): Unit = synchronized { super.clear() } /** Returns an iterator over all elements on the stack. This iterator * is stable with respect to state changes in the stack object; i.e. diff --git a/src/library/scala/collection/mutable/Traversable.scala b/src/library/scala/collection/mutable/Traversable.scala index e36ffc847f..d7ea376d28 100644 --- a/src/library/scala/collection/mutable/Traversable.scala +++ b/src/library/scala/collection/mutable/Traversable.scala @@ -8,7 +8,8 @@ -package scala.collection +package scala +package collection package mutable import generic._ diff --git a/src/library/scala/collection/mutable/TreeSet.scala b/src/library/scala/collection/mutable/TreeSet.scala index 5197af1b04..f849eea569 100644 --- a/src/library/scala/collection/mutable/TreeSet.scala +++ b/src/library/scala/collection/mutable/TreeSet.scala @@ -6,10 +6,13 @@ ** |/ ** \* */ -package scala.collection +package scala +package collection package mutable import generic._ +import scala.collection.immutable.{RedBlackTree => RB} +import scala.runtime.ObjectRef /** * @define Coll `mutable.TreeSet` @@ -29,95 +32,85 @@ object TreeSet extends MutableSortedSetFactory[TreeSet] { } /** - * A mutable SortedSet using an immutable AVL Tree as underlying data structure. + * A mutable SortedSet using an immutable RedBlack Tree as underlying data structure. * * @author Lucien Pereira * */ -class TreeSet[A](implicit val ordering: Ordering[A]) extends SortedSet[A] with SetLike[A, TreeSet[A]] +@deprecatedInheritance("TreeSet is not designed to enable meaningful subclassing.", "2.11.0") +class TreeSet[A] private (treeRef: ObjectRef[RB.Tree[A, Null]], from: Option[A], until: Option[A])(implicit val ordering: Ordering[A]) + extends SortedSet[A] with SetLike[A, TreeSet[A]] with SortedSetLike[A, TreeSet[A]] with Set[A] with Serializable { - // Projection constructor - private def this(base: Option[TreeSet[A]], from: Option[A], until: Option[A])(implicit ordering: Ordering[A]) { - this(); - this.base = base - this.from = from - this.until = until - } - - private var base: Option[TreeSet[A]] = None - - private var from: Option[A] = None - - private var until: Option[A] = None - - private var avl: AVLTree[A] = Leaf - - private var cardinality: Int = 0 - - def resolve: TreeSet[A] = base.getOrElse(this) + if (ordering eq null) + throw new NullPointerException("ordering must not be null") - private def isLeftAcceptable(from: Option[A], ordering: Ordering[A])(a: A): Boolean = - from.map(x => ordering.gteq(a, x)).getOrElse(true) + def this()(implicit ordering: Ordering[A]) = this(new ObjectRef(null), None, None) - private def isRightAcceptable(until: Option[A], ordering: Ordering[A])(a: A): Boolean = - until.map(x => ordering.lt(a, x)).getOrElse(true) - - /** - * Cardinality store the set size, unfortunately a - * set view (given by rangeImpl) - * cannot take advantage of this optimisation - * - */ - override def size: Int = base.map(_ => super.size).getOrElse(cardinality) + override def size: Int = RB.countInRange(treeRef.elem, from, until) override def stringPrefix = "TreeSet" override def empty: TreeSet[A] = TreeSet.empty - override def rangeImpl(from: Option[A], until: Option[A]): TreeSet[A] = new TreeSet(Some(this), from, until) + private def pickBound(comparison: (A, A) => A, oldBound: Option[A], newBound: Option[A]) = (newBound, oldBound) match { + case (Some(newB), Some(oldB)) => Some(comparison(newB, oldB)) + case (None, _) => oldBound + case _ => newBound + } + + override def rangeImpl(fromArg: Option[A], untilArg: Option[A]): TreeSet[A] = { + val newFrom = pickBound(ordering.max, fromArg, from) + val newUntil = pickBound(ordering.min, untilArg, until) + + new TreeSet(treeRef, newFrom, newUntil) + } override def -=(elem: A): this.type = { - try { - resolve.avl = resolve.avl.remove(elem, ordering) - resolve.cardinality = resolve.cardinality - 1 - } catch { - case e: NoSuchElementException => () - } + treeRef.elem = RB.delete(treeRef.elem, elem) this } override def +=(elem: A): this.type = { - try { - resolve.avl = resolve.avl.insert(elem, ordering) - resolve.cardinality = resolve.cardinality + 1 - } catch { - case e: IllegalArgumentException => () - } + treeRef.elem = RB.update(treeRef.elem, elem, null, overwrite = false) this } /** * Thanks to the immutable nature of the - * underlying AVL Tree, we can share it with + * underlying Tree, we can share it with * the clone. So clone complexity in time is O(1). * */ - override def clone(): TreeSet[A] = { - val clone = new TreeSet[A](base, from, until) - clone.avl = resolve.avl - clone.cardinality = resolve.cardinality - clone - } + override def clone(): TreeSet[A] = + new TreeSet[A](new ObjectRef(treeRef.elem), from, until) + + private val notProjection = !(from.isDefined || until.isDefined) override def contains(elem: A): Boolean = { - isLeftAcceptable(from, ordering)(elem) && - isRightAcceptable(until, ordering)(elem) && - resolve.avl.contains(elem, ordering) + def leftAcceptable: Boolean = from match { + case Some(lb) => ordering.gteq(elem, lb) + case _ => true + } + + def rightAcceptable: Boolean = until match { + case Some(ub) => ordering.lt(elem, ub) + case _ => true + } + + (notProjection || (leftAcceptable && rightAcceptable)) && + RB.contains(treeRef.elem, elem) } - override def iterator: Iterator[A] = resolve.avl.iterator - .dropWhile(e => !isLeftAcceptable(from, ordering)(e)) - .takeWhile(e => isRightAcceptable(until, ordering)(e)) + override def iterator: Iterator[A] = iteratorFrom(None) + override def keysIteratorFrom(start: A) = iteratorFrom(Some(start)) + + private def iteratorFrom(start: Option[A]) = { + val it = RB.keysIterator(treeRef.elem, pickBound(ordering.max, from, start)) + until match { + case None => it + case Some(ub) => it takeWhile (k => ordering.lt(k, ub)) + } + } } diff --git a/src/library/scala/collection/mutable/Undoable.scala b/src/library/scala/collection/mutable/Undoable.scala index 0c0e8fed3e..482d618165 100644 --- a/src/library/scala/collection/mutable/Undoable.scala +++ b/src/library/scala/collection/mutable/Undoable.scala @@ -8,7 +8,8 @@ -package scala.collection +package scala +package collection package mutable diff --git a/src/library/scala/collection/mutable/UnrolledBuffer.scala b/src/library/scala/collection/mutable/UnrolledBuffer.scala index 9b48c8f24f..1f89199bdc 100644 --- a/src/library/scala/collection/mutable/UnrolledBuffer.scala +++ b/src/library/scala/collection/mutable/UnrolledBuffer.scala @@ -6,7 +6,8 @@ ** |/ ** \* */ -package scala.collection.mutable +package scala +package collection.mutable import scala.collection.AbstractIterator import scala.collection.Iterator @@ -42,6 +43,7 @@ import scala.reflect.ClassTag * */ @SerialVersionUID(1L) +@deprecatedInheritance("UnrolledBuffer is not designed to enable meaningful subclassing.", "2.11.0") class UnrolledBuffer[T](implicit val tag: ClassTag[T]) extends scala.collection.mutable.AbstractBuffer[T] with scala.collection.mutable.Buffer[T] @@ -66,7 +68,20 @@ extends scala.collection.mutable.AbstractBuffer[T] protected def newUnrolled = new Unrolled[T](this) - private[collection] def calcNextLength(sz: Int) = sz + // The below would allow more flexible behavior without requiring inheritance + // that is risky because all the important internals are private. + // private var myLengthPolicy: Int => Int = x => x + // + // /** Specifies how the array lengths should vary. + // * + // * By default, `UnrolledBuffer` uses arrays of a fixed size. A length + // * policy can be given that changes this scheme to, for instance, an + // * exponential growth. + // * + // * @param nextLength computes the length of the next array from the length of the latest one + // */ + // def setLengthPolicy(nextLength: Int => Int): Unit = { myLengthPolicy = nextLength } + private[collection] def calcNextLength(sz: Int) = sz // myLengthPolicy(sz) def classTagCompanion = UnrolledBuffer @@ -87,7 +102,7 @@ extends scala.collection.mutable.AbstractBuffer[T] // `that` is no longer usable, so clear it // here we rely on the fact that `clear` allocates // new nodes instead of modifying the previous ones - that.clear + that.clear() // return a reference to this this @@ -123,7 +138,7 @@ extends scala.collection.mutable.AbstractBuffer[T] val r = node.array(pos) scan() r - } else Iterator.empty.next + } else Iterator.empty.next() } // this should be faster than the iterator diff --git a/src/library/scala/collection/mutable/WeakHashMap.scala b/src/library/scala/collection/mutable/WeakHashMap.scala index 70e428c9b6..433d054bfc 100644 --- a/src/library/scala/collection/mutable/WeakHashMap.scala +++ b/src/library/scala/collection/mutable/WeakHashMap.scala @@ -6,7 +6,8 @@ ** |/ ** \* */ -package scala.collection +package scala +package collection package mutable import generic._ diff --git a/src/library/scala/collection/mutable/WrappedArray.scala b/src/library/scala/collection/mutable/WrappedArray.scala index b83724090c..53fca9f779 100644 --- a/src/library/scala/collection/mutable/WrappedArray.scala +++ b/src/library/scala/collection/mutable/WrappedArray.scala @@ -8,7 +8,8 @@ -package scala.collection +package scala +package collection package mutable import scala.reflect.ClassTag diff --git a/src/library/scala/collection/mutable/WrappedArrayBuilder.scala b/src/library/scala/collection/mutable/WrappedArrayBuilder.scala index 7e0210311c..bfe95a11ab 100644 --- a/src/library/scala/collection/mutable/WrappedArrayBuilder.scala +++ b/src/library/scala/collection/mutable/WrappedArrayBuilder.scala @@ -8,10 +8,10 @@ -package scala.collection +package scala +package collection package mutable -import generic._ import scala.reflect.ClassTag import scala.runtime.ScalaRunTime._ diff --git a/src/library/scala/collection/parallel/Combiner.scala b/src/library/scala/collection/parallel/Combiner.scala index 00993c09ff..abccf5d402 100644 --- a/src/library/scala/collection/parallel/Combiner.scala +++ b/src/library/scala/collection/parallel/Combiner.scala @@ -6,16 +6,13 @@ ** |/ ** \* */ - -package scala.collection.parallel - +package scala +package collection.parallel import scala.collection.Parallel import scala.collection.mutable.Builder import scala.collection.generic.Sizing - - /** The base trait for all combiners. * A combiner incremental collection construction just like * a regular builder, but also implements an efficient merge operation of two builders @@ -33,11 +30,11 @@ import scala.collection.generic.Sizing * @since 2.9 */ trait Combiner[-Elem, +To] extends Builder[Elem, To] with Sizing with Parallel { - + @transient @volatile var _combinerTaskSupport = defaultTaskSupport - + def combinerTaskSupport = { val cts = _combinerTaskSupport if (cts eq null) { @@ -45,9 +42,9 @@ trait Combiner[-Elem, +To] extends Builder[Elem, To] with Sizing with Parallel { defaultTaskSupport } else cts } - + def combinerTaskSupport_=(cts: TaskSupport) = _combinerTaskSupport = cts - + /** Combines the contents of the receiver builder and the `other` builder, * producing a new builder containing both their elements. * @@ -81,18 +78,16 @@ trait Combiner[-Elem, +To] extends Builder[Elem, To] with Sizing with Parallel { * By default, this method returns `false`. */ def canBeShared: Boolean = false - + /** Constructs the result and sets the appropriate tasksupport object to the resulting collection * if this is applicable. */ def resultWithTaskSupport: To = { - val res = result + val res = result() setTaskSupport(res, combinerTaskSupport) } - } - /* private[collection] trait EnvironmentPassingCombiner[-Elem, +To] extends Combiner[Elem, To] { abstract override def result = { @@ -101,12 +96,3 @@ private[collection] trait EnvironmentPassingCombiner[-Elem, +To] extends Combine } } */ - - - - - - - - - diff --git a/src/library/scala/collection/parallel/ParIterable.scala b/src/library/scala/collection/parallel/ParIterable.scala index 2b24c88139..2ceeb18eef 100644 --- a/src/library/scala/collection/parallel/ParIterable.scala +++ b/src/library/scala/collection/parallel/ParIterable.scala @@ -6,12 +6,12 @@ ** |/ ** \* */ -package scala.collection.parallel +package scala +package collection.parallel import scala.collection.GenIterable import scala.collection.generic._ import scala.collection.parallel.mutable.ParArrayCombiner -import scala.collection.parallel.mutable.ParArray /** A template trait for parallel iterable collections. * diff --git a/src/library/scala/collection/parallel/ParIterableLike.scala b/src/library/scala/collection/parallel/ParIterableLike.scala index 0f06ff37af..445edd23cb 100644 --- a/src/library/scala/collection/parallel/ParIterableLike.scala +++ b/src/library/scala/collection/parallel/ParIterableLike.scala @@ -6,11 +6,8 @@ ** |/ ** \* */ - -package scala.collection.parallel - - - +package scala +package collection.parallel import scala.collection.mutable.Builder import scala.collection.mutable.ArrayBuffer @@ -32,6 +29,8 @@ import scala.annotation.unchecked.uncheckedVariance import scala.annotation.unchecked.uncheckedStable import scala.language.{ higherKinds, implicitConversions } +import scala.collection.parallel.ParallelCollectionImplicits._ + /** A template trait for parallel collections of type `ParIterable[T]`. * @@ -171,9 +170,9 @@ self: ParIterableLike[T, Repr, Sequential] => /** The task support object which is responsible for scheduling and * load-balancing tasks to processors. - * + * * @see [[scala.collection.parallel.TaskSupport]] - */ + */ def tasksupport = { val ts = _tasksupport if (ts eq null) { @@ -188,18 +187,18 @@ self: ParIterableLike[T, Repr, Sequential] => * A task support object can be changed in a parallel collection after it * has been created, but only during a quiescent period, i.e. while there * are no concurrent invocations to parallel collection methods. - * - * Here is a way to change the task support of a parallel collection: - * - * {{{ - * import scala.collection.parallel._ - * val pc = mutable.ParArray(1, 2, 3) - * pc.tasksupport = new ForkJoinTaskSupport( - * new scala.concurrent.forkjoin.ForkJoinPool(2)) - * }}} + * + * Here is a way to change the task support of a parallel collection: + * + * {{{ + * import scala.collection.parallel._ + * val pc = mutable.ParArray(1, 2, 3) + * pc.tasksupport = new ForkJoinTaskSupport( + * new scala.concurrent.forkjoin.ForkJoinPool(2)) + * }}} * * @see [[scala.collection.parallel.TaskSupport]] - */ + */ def tasksupport_=(ts: TaskSupport) = _tasksupport = ts def seq: Sequential @@ -214,7 +213,7 @@ self: ParIterableLike[T, Repr, Sequential] => def nonEmpty = size != 0 - def head = iterator.next + def head = iterator.next() def headOption = if (nonEmpty) Some(head) else None @@ -419,8 +418,8 @@ self: ParIterableLike[T, Repr, Sequential] => * may be invoked arbitrary number of times. * * For example, one might want to process some elements and then produce a `Set`. In this - * case, `seqop` would process an element and append it to the list, while `combop` - * would concatenate two lists from different partitions together. The initial value + * case, `seqop` would process an element and append it to the set, while `combop` + * would concatenate two sets from different partitions together. The initial value * `z` would be an empty set. * * {{{ @@ -433,12 +432,13 @@ self: ParIterableLike[T, Repr, Sequential] => * @tparam S the type of accumulated results * @param z the initial value for the accumulated result of the partition - this * will typically be the neutral element for the `seqop` operator (e.g. - * `Nil` for list concatenation or `0` for summation) + * `Nil` for list concatenation or `0` for summation) and may be evaluated + * more than once * @param seqop an operator used to accumulate results within a partition * @param combop an associative operator used to combine results from different partitions */ - def aggregate[S](z: S)(seqop: (S, T) => S, combop: (S, S) => S): S = { - tasksupport.executeAndWaitResult(new Aggregate(z, seqop, combop, splitter)) + def aggregate[S](z: =>S)(seqop: (S, T) => S, combop: (S, S) => S): S = { + tasksupport.executeAndWaitResult(new Aggregate(() => z, seqop, combop, splitter)) } def foldLeft[S](z: S)(op: (S, T) => S): S = seq.foldLeft(z)(op) @@ -453,7 +453,7 @@ self: ParIterableLike[T, Repr, Sequential] => def reduceRightOption[U >: T](op: (T, U) => U): Option[U] = seq.reduceRightOption(op) - /** Applies a function `f` to all the elements of $coll in a undefined order. + /** Applies a function `f` to all the elements of $coll in an undefined order. * * @tparam U the result type of the function applied to each element, which is always discarded * @param f function applied to each element @@ -589,6 +589,8 @@ self: ParIterableLike[T, Repr, Sequential] => } } + def withFilter(pred: T => Boolean): Repr = filter(pred) + def filter(pred: T => Boolean): Repr = { tasksupport.executeAndWaitResult(new Filter(pred, combinerFactory, splitter) mapResult { _.resultWithTaskSupport }) } @@ -626,7 +628,7 @@ self: ParIterableLike[T, Repr, Sequential] => val b = bf(repr) this.splitter.copy2builder[U, That, Builder[U, That]](b) for (elem <- that.seq) b += elem - setTaskSupport(b.result, tasksupport) + setTaskSupport(b.result(), tasksupport) } } @@ -727,7 +729,7 @@ self: ParIterableLike[T, Repr, Sequential] => tree => tasksupport.executeAndWaitResult(new FromScanTree(tree, z, op, combinerFactory(() => bf(repr).asCombiner)) mapResult { cb => cb.resultWithTaskSupport }) - }) else setTaskSupport((bf(repr) += z).result, tasksupport) + }) else setTaskSupport((bf(repr) += z).result(), tasksupport) } else setTaskSupport(seq.scan(z)(op)(bf2seq(bf)), tasksupport) } else setTaskSupport(seq.scan(z)(op)(bf2seq(bf)), tasksupport) @@ -819,10 +821,10 @@ self: ParIterableLike[T, Repr, Sequential] => def zip[U >: T, S, That](that: GenIterable[S])(implicit bf: CanBuildFrom[Repr, (U, S), That]): That = if (bf(repr).isCombiner && that.isParSeq) { val thatseq = that.asParSeq - tasksupport.executeAndWaitResult(new Zip(combinerFactory(() => bf(repr).asCombiner), splitter, thatseq.splitter) mapResult { _.resultWithTaskSupport }); + tasksupport.executeAndWaitResult(new Zip(combinerFactory(() => bf(repr).asCombiner), splitter, thatseq.splitter) mapResult { _.resultWithTaskSupport }) } else setTaskSupport(seq.zip(that)(bf2seq(bf)), tasksupport) - def zipWithIndex[U >: T, That](implicit bf: CanBuildFrom[Repr, (U, Int), That]): That = this zip immutable.ParRange(0, size, 1, false) + def zipWithIndex[U >: T, That](implicit bf: CanBuildFrom[Repr, (U, Int), That]): That = this zip immutable.ParRange(0, size, 1, inclusive = false) def zipAll[S, U >: T, That](that: GenIterable[S], thisElem: U, thatElem: S)(implicit bf: CanBuildFrom[Repr, (U, S), That]): That = if (bf(repr).isCombiner && that.isParSeq) { val thatseq = that.asParSeq @@ -830,25 +832,19 @@ self: ParIterableLike[T, Repr, Sequential] => new ZipAll(size max thatseq.length, thisElem, thatElem, combinerFactory(() => bf(repr).asCombiner), splitter, thatseq.splitter) mapResult { _.resultWithTaskSupport } - ); + ) } else setTaskSupport(seq.zipAll(that, thisElem, thatElem)(bf2seq(bf)), tasksupport) protected def toParCollection[U >: T, That](cbf: () => Combiner[U, That]): That = { - tasksupport.executeAndWaitResult(new ToParCollection(combinerFactory(cbf), splitter) mapResult { _.resultWithTaskSupport }); + tasksupport.executeAndWaitResult(new ToParCollection(combinerFactory(cbf), splitter) mapResult { _.resultWithTaskSupport }) } protected def toParMap[K, V, That](cbf: () => Combiner[(K, V), That])(implicit ev: T <:< (K, V)): That = { tasksupport.executeAndWaitResult(new ToParMap(combinerFactory(cbf), splitter)(ev) mapResult { _.resultWithTaskSupport }) } - def view = new ParIterableView[T, Repr, Sequential] { - protected lazy val underlying = self.repr - protected[this] def viewIdentifier = "" - protected[this] def viewIdString = "" - override def seq = self.seq.view - def splitter = self.splitter - def size = splitter.remaining - } + @deprecated("Use .seq.view instead", "2.11.0") + def view = seq.view override def toArray[U >: T: ClassTag]: Array[U] = { val arr = new Array[U](size) @@ -877,13 +873,13 @@ self: ParIterableLike[T, Repr, Sequential] => override def toSet[U >: T]: immutable.ParSet[U] = toParCollection[U, immutable.ParSet[U]](() => immutable.ParSet.newCombiner[U]) override def toMap[K, V](implicit ev: T <:< (K, V)): immutable.ParMap[K, V] = toParMap[K, V, immutable.ParMap[K, V]](() => immutable.ParMap.newCombiner[K, V]) - + override def toVector: Vector[T] = to[Vector] override def to[Col[_]](implicit cbf: CanBuildFrom[Nothing, T, Col[T @uncheckedVariance]]): Col[T @uncheckedVariance] = if (cbf().isCombiner) { toParCollection[T, Col[T]](() => cbf().asCombiner) } else seq.to(cbf) - + /* tasks */ protected trait StrictSplitterCheckTask[R, Tp] extends Task[R, Tp] { @@ -903,7 +899,7 @@ self: ParIterableLike[T, Repr, Sequential] => protected[this] def newSubtask(p: IterableSplitter[T]): Accessor[R, Tp] def shouldSplitFurther = pit.shouldSplitFurther(self.repr, tasksupport.parallelismLevel) def split = pit.splitWithSignalling.map(newSubtask(_)) // default split procedure - private[parallel] override def signalAbort = pit.abort + private[parallel] override def signalAbort = pit.abort() override def toString = this.getClass.getSimpleName + "(" + pit.toString + ")(" + result + ")(supername: " + super.toString + ")" } @@ -920,8 +916,8 @@ self: ParIterableLike[T, Repr, Sequential] => def combineResults(fr: FR, sr: SR): R @volatile var result: R = null.asInstanceOf[R] private[parallel] override def signalAbort() { - ft.signalAbort - st.signalAbort + ft.signalAbort() + st.signalAbort() } protected def mergeSubtasks() { ft mergeThrowables st @@ -935,9 +931,9 @@ self: ParIterableLike[T, Repr, Sequential] => (f: First, s: Second) extends Composite[FR, SR, R, First, Second](f, s) { def leaf(prevr: Option[R]) = { - tasksupport.executeAndWaitResult(ft) - tasksupport.executeAndWaitResult(st) - mergeSubtasks + tasksupport.executeAndWaitResult(ft) : Any + tasksupport.executeAndWaitResult(st) : Any + mergeSubtasks() } } @@ -946,10 +942,10 @@ self: ParIterableLike[T, Repr, Sequential] => (f: First, s: Second) extends Composite[FR, SR, R, First, Second](f, s) { def leaf(prevr: Option[R]) = { - val ftfuture = tasksupport.execute(ft) - tasksupport.executeAndWaitResult(st) + val ftfuture: () => Any = tasksupport.execute(ft) + tasksupport.executeAndWaitResult(st) : Any ftfuture() - mergeSubtasks + mergeSubtasks() } } @@ -962,7 +958,7 @@ self: ParIterableLike[T, Repr, Sequential] => result = map(initialResult) } private[parallel] override def signalAbort() { - inner.signalAbort + inner.signalAbort() } override def requiresStrictSplitters = inner.requiresStrictSplitters } @@ -1005,10 +1001,10 @@ self: ParIterableLike[T, Repr, Sequential] => override def merge(that: Fold[U]) = result = op(result, that.result) } - protected[this] class Aggregate[S](z: S, seqop: (S, T) => S, combop: (S, S) => S, protected[this] val pit: IterableSplitter[T]) + protected[this] class Aggregate[S](z: () => S, seqop: (S, T) => S, combop: (S, S) => S, protected[this] val pit: IterableSplitter[T]) extends Accessor[S, Aggregate[S]] { @volatile var result: S = null.asInstanceOf[S] - def leaf(prevr: Option[S]) = result = pit.foldLeft(z)(seqop) + def leaf(prevr: Option[S]) = result = pit.foldLeft(z())(seqop) protected[this] def newSubtask(p: IterableSplitter[T]) = new Aggregate(z, seqop, combop, p) override def merge(that: Aggregate[S]) = result = combop(result, that.result) } @@ -1084,7 +1080,7 @@ self: ParIterableLike[T, Repr, Sequential] => protected[this] class Forall(pred: T => Boolean, protected[this] val pit: IterableSplitter[T]) extends Accessor[Boolean, Forall] { @volatile var result: Boolean = true - def leaf(prev: Option[Boolean]) = { if (!pit.isAborted) result = pit.forall(pred); if (result == false) pit.abort } + def leaf(prev: Option[Boolean]) = { if (!pit.isAborted) result = pit.forall(pred); if (result == false) pit.abort() } protected[this] def newSubtask(p: IterableSplitter[T]) = new Forall(pred, p) override def merge(that: Forall) = result = result && that.result } @@ -1092,7 +1088,7 @@ self: ParIterableLike[T, Repr, Sequential] => protected[this] class Exists(pred: T => Boolean, protected[this] val pit: IterableSplitter[T]) extends Accessor[Boolean, Exists] { @volatile var result: Boolean = false - def leaf(prev: Option[Boolean]) = { if (!pit.isAborted) result = pit.exists(pred); if (result == true) pit.abort } + def leaf(prev: Option[Boolean]) = { if (!pit.isAborted) result = pit.exists(pred); if (result == true) pit.abort() } protected[this] def newSubtask(p: IterableSplitter[T]) = new Exists(pred, p) override def merge(that: Exists) = result = result || that.result } @@ -1100,7 +1096,7 @@ self: ParIterableLike[T, Repr, Sequential] => protected[this] class Find[U >: T](pred: T => Boolean, protected[this] val pit: IterableSplitter[T]) extends Accessor[Option[U], Find[U]] { @volatile var result: Option[U] = None - def leaf(prev: Option[Option[U]]) = { if (!pit.isAborted) result = pit.find(pred); if (result != None) pit.abort } + def leaf(prev: Option[Option[U]]) = { if (!pit.isAborted) result = pit.find(pred); if (result != None) pit.abort() } protected[this] def newSubtask(p: IterableSplitter[T]) = new Find(pred, p) override def merge(that: Find[U]) = if (this.result == None) result = that.result } @@ -1152,7 +1148,7 @@ self: ParIterableLike[T, Repr, Sequential] => // note: HashMapCombiner doesn't merge same keys until evaluation val cb = mcf() while (pit.hasNext) { - val elem = pit.next + val elem = pit.next() cb += f(elem) -> elem } result = cb @@ -1473,9 +1469,9 @@ self: ParIterableLike[T, Repr, Sequential] => /* alias methods */ - def /:[S](z: S)(op: (S, T) => S): S = foldLeft(z)(op); + def /:[S](z: S)(op: (S, T) => S): S = foldLeft(z)(op) - def :\[S](z: S)(op: (T, S) => S): S = foldRight(z)(op); + def :\[S](z: S)(op: (T, S) => S): S = foldRight(z)(op) /* debug information */ @@ -1488,7 +1484,7 @@ self: ParIterableLike[T, Repr, Sequential] => def debugBuffer: ArrayBuffer[String] = null private[parallel] def debugclear() = synchronized { - debugBuffer.clear + debugBuffer.clear() } private[parallel] def debuglog(s: String) = synchronized { @@ -1504,31 +1500,3 @@ self: ParIterableLike[T, Repr, Sequential] => }) } - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/library/scala/collection/parallel/ParIterableView.scala b/src/library/scala/collection/parallel/ParIterableView.scala deleted file mode 100644 index 7644e1bd12..0000000000 --- a/src/library/scala/collection/parallel/ParIterableView.scala +++ /dev/null @@ -1,46 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala.collection.parallel - -import scala.collection.{ Parallel, IterableView, GenIterableView, Iterator } -import scala.collection.generic.CanCombineFrom - -/** A template view of a non-strict view of a parallel iterable collection. - * - * @tparam T the type of elements - * @tparam Coll the type of the parallel collection this view was created from - * @tparam CollSeq the type of the sequential collection corresponding to the underlying parallel collection - * - * @since 2.9 - */ -trait ParIterableView[+T, +Coll <: Parallel, +CollSeq] -extends ParIterableViewLike[T, Coll, CollSeq, ParIterableView[T, Coll, CollSeq], IterableView[T, CollSeq]] - with GenIterableView[T, Coll] - - -object ParIterableView { - abstract class NoCombiner[T] extends Combiner[T, Nothing] { -// self: EnvironmentPassingCombiner[T, Nothing] => - def +=(elem: T): this.type = this - def iterator: Iterator[T] = Iterator.empty - def result() = throw new UnsupportedOperationException("ParIterableView.Combiner.result") - def size = throw new UnsupportedOperationException("ParIterableView.Combiner.size") - def clear() {} - def combine[N <: T, NewTo >: Nothing](other: Combiner[N, NewTo]) = - throw new UnsupportedOperationException("ParIterableView.Combiner.result") - } - - type Coll = ParIterableView[_, C, _] forSome { type C <: ParIterable[_] } - - implicit def canBuildFrom[T]: CanCombineFrom[Coll, T, ParIterableView[T, ParIterable[T], Iterable[T]]] = - new CanCombineFrom[Coll, T, ParIterableView[T, ParIterable[T], Iterable[T]]] { - def apply(from: Coll) = new NoCombiner[T] {} // was: with EnvironmentPassingCombiner[T, Nothing] - def apply() = new NoCombiner[T] {} // was: with EnvironmentPassingCombiner[T, Nothing] - } -} diff --git a/src/library/scala/collection/parallel/ParIterableViewLike.scala b/src/library/scala/collection/parallel/ParIterableViewLike.scala deleted file mode 100644 index 0ecd6bd9ec..0000000000 --- a/src/library/scala/collection/parallel/ParIterableViewLike.scala +++ /dev/null @@ -1,203 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala.collection.parallel - -import scala.collection.Parallel -import scala.collection.{ IterableView, IterableViewLike } -import scala.collection.{ GenIterableView, GenIterableViewLike } -import scala.collection.GenTraversableOnce -import scala.collection.GenTraversable -import scala.collection.GenIterable -import scala.collection.GenSeq -import scala.collection.generic.{ CanBuildFrom, SliceInterval } -import scala.collection.generic.CanCombineFrom -import scala.collection.parallel.immutable.ParRange -import scala.language.implicitConversions - - - -/** A template view of a non-strict view of parallel iterable collection. - * - * '''Note:''' Regular view traits have type parameters used to carry information - * about the type of the elements, type of the collection they are derived from and - * their own actual representation type. Parallel views have an additional parameter - * which carries information about the type of the sequential version of the view. - * - * @tparam T the type of the elements this view can traverse - * @tparam Coll the type of the parallel collection this view is derived from - * @tparam CollSeq the type of the sequential collection corresponding to the underlying parallel collection - * @tparam This the actual representation type of this view - * @tparam ThisSeq the type of the sequential representation of this view - * - * @since 2.9 - */ -trait ParIterableViewLike[+T, - +Coll <: Parallel, - +CollSeq, - +This <: ParIterableView[T, Coll, CollSeq] with ParIterableViewLike[T, Coll, CollSeq, This, ThisSeq], - +ThisSeq <: IterableView[T, CollSeq] with IterableViewLike[T, CollSeq, ThisSeq]] -extends GenIterableView[T, Coll] - with GenIterableViewLike[T, Coll, This] - with ParIterable[T] - with ParIterableLike[T, This, ThisSeq] -{ -self => - - override def foreach[U](f: T => U): Unit = super[ParIterableLike].foreach(f) - override protected[this] def newCombiner: Combiner[T, This] = throw new UnsupportedOperationException(this + ".newCombiner"); - protected[this] def viewIdentifier: String - protected[this] def viewIdString: String - - protected def underlying: Coll - - /* wrappers */ - - trait Transformed[+S] extends ParIterableView[S, Coll, CollSeq] with super.Transformed[S] { - override def splitter: IterableSplitter[S] - override def iterator = splitter - def size = splitter.remaining - } - - trait Sliced extends super.Sliced with Transformed[T] { - // override def slice(from1: Int, until1: Int): This = newSliced(from1 max 0, until1 max 0).asInstanceOf[This] - def splitter: IterableSplitter[T] = self.splitter.slice(from, until) - override def seq = self.seq.slice(from, until) - } - - trait Mapped[S] extends super.Mapped[S] with Transformed[S]{ - def splitter: IterableSplitter[S] = self.splitter.map(mapping) - override def seq = self.seq.map(mapping).asInstanceOf[IterableView[S, CollSeq]] - } - - // only use if other is a ParIterable, otherwise force - trait Appended[U >: T] extends super.Appended[U] with Transformed[U] { - def restPar: ParIterable[U] = rest.asParIterable - def splitter: IterableSplitter[U] = self.splitter.appendParIterable[U, IterableSplitter[U]](restPar.splitter) - override def seq = self.seq.++(rest).asInstanceOf[IterableView[U, CollSeq]] - } - - trait Forced[S] extends super.Forced[S] with Transformed[S] { - def forcedPar: ParIterable[S] = forced.asParIterable - def splitter: IterableSplitter[S] = forcedPar.splitter - override def seq = forcedPar.seq.view.asInstanceOf[IterableView[S, CollSeq]] - } - - // only use if other is a ParSeq, otherwise force - trait Zipped[S] extends super.Zipped[S] with Transformed[(T, S)] { - def otherPar: ParSeq[S] = other.asParSeq - def splitter: IterableSplitter[(T, S)] = self.splitter zipParSeq otherPar.splitter - override def seq = (self.seq zip other).asInstanceOf[IterableView[(T, S), CollSeq]] - } - - // only use if other is a ParSeq, otherwise force - trait ZippedAll[U >: T, S] extends super.ZippedAll[U, S] with Transformed[(U, S)] { - def otherPar: ParSeq[S] = other.asParSeq - def splitter: IterableSplitter[(U, S)] = self.splitter.zipAllParSeq(otherPar.splitter, thisElem, thatElem) - override def seq = (self.seq.zipAll(other, thisElem, thatElem)).asInstanceOf[IterableView[(U, S), CollSeq]] - } - - protected[this] def thisParSeq: ParSeq[T] = mutable.ParArray.fromTraversables(this.iterator) - private[this] implicit def asThis(xs: Transformed[T]): This = xs.asInstanceOf[This] - - /* operation overrides */ - - override def take(n: Int): This = newSliced(SliceInterval(0, n)) - override def drop(n: Int): This = newSliced(SliceInterval(n, splitter.remaining)) - override def splitAt(n: Int): (This, This) = (take(n), drop(n)) - override def slice(from: Int, until: Int): This = newSliced(SliceInterval(from, until)) - override def map[S, That](f: T => S)(implicit bf: CanBuildFrom[This, S, That]): That = newMapped(f).asInstanceOf[That] - override def ++[U >: T, That](xs: GenTraversableOnce[U])(implicit bf: CanBuildFrom[This, U, That]): That = newAppendedTryParIterable(xs.toTraversable).asInstanceOf[That] - - override def filter(p: T => Boolean): This = newForced(thisParSeq.filter(p)).asInstanceOf[This] - override def filterNot(p: T => Boolean): This = newForced(thisParSeq.filterNot(p)).asInstanceOf[This] - override def partition(p: T => Boolean): (This, This) = { - val (t, f) = thisParSeq.partition(p) - (newForced(t).asInstanceOf[This], newForced(f).asInstanceOf[This]) - } - override def takeWhile(p: T => Boolean): This = newForced(thisParSeq.takeWhile(p)).asInstanceOf[This] - override def dropWhile(p: T => Boolean): This = newForced(thisParSeq.dropWhile(p)).asInstanceOf[This] - override def span(p: T => Boolean): (This, This) = { - val (pref, suff) = thisParSeq.span(p) - (newForced(pref).asInstanceOf[This], newForced(suff).asInstanceOf[This]) - } - override def flatMap[S, That](f: T => GenTraversableOnce[S])(implicit bf: CanBuildFrom[This, S, That]): That = newForced(thisParSeq.flatMap(f)).asInstanceOf[That] - - override def zip[U >: T, S, That](that: GenIterable[S])(implicit bf: CanBuildFrom[This, (U, S), That]): That = newZippedTryParSeq(that).asInstanceOf[That] - override def zipWithIndex[U >: T, That](implicit bf: CanBuildFrom[This, (U, Int), That]): That = - newZipped(ParRange(0, splitter.remaining, 1, false)).asInstanceOf[That] - override def zipAll[S, U >: T, That](that: GenIterable[S], thisElem: U, thatElem: S)(implicit bf: CanBuildFrom[This, (U, S), That]): That = - newZippedAllTryParSeq(that, thisElem, thatElem).asInstanceOf[That] - - override def force[U >: T, That](implicit bf: CanBuildFrom[Coll, U, That]) = bf ifParallel { pbf => - tasksupport.executeAndWaitResult(new Force(pbf, splitter).mapResult(_.result).asInstanceOf[Task[That, ResultMapping[_, Force[U, That], That]]]) - } otherwise { - val b = bf(underlying) - b ++= this.iterator - b.result - } - - /* wrapper virtual ctors */ - - protected def newSliced(_endpoints: SliceInterval): Transformed[T] = new { val endpoints = _endpoints } with Sliced - protected def newMapped[S](f: T => S): Transformed[S] = new Mapped[S] { val mapping = f } - protected def newForced[S](xs: => GenSeq[S]): Transformed[S] = new Forced[S] { val forced = xs } - protected def newAppended[U >: T](that: GenTraversable[U]): Transformed[U] = new Appended[U] { val rest = that } - protected def newDroppedWhile(p: T => Boolean) = unsupported - protected def newTakenWhile(p: T => Boolean) = unsupported - protected def newFlatMapped[S](f: T => GenTraversableOnce[S]) = unsupported - protected def newFiltered(p: T => Boolean) = unsupported - protected def newZipped[S](that: GenIterable[S]): Transformed[(T, S)] = new Zipped[S] { val other = that } - protected def newZippedAll[U >: T, S](that: GenIterable[S], _thisElem: U, _thatElem: S): Transformed[(U, S)] = new ZippedAll[U, S] { - val other = that - val thisElem = _thisElem - val thatElem = _thatElem - } - - /* argument sequence dependent ctors */ - - protected def newForcedTryParIterable[S](xs: => GenSeq[S]): Transformed[S] = { - if (xs.isParIterable) newForced[S](xs) - else newForced(mutable.ParArray.fromTraversables(xs)) - } - protected def newAppendedTryParIterable[U >: T](that: GenTraversable[U]): Transformed[U] = { - // we only append if `that` is a parallel iterable, i.e. it has a splitter - if (that.isParIterable) newAppended(that) - else newAppended(mutable.ParArray.fromTraversables(that)) - } - protected def newZippedTryParSeq[S](that: GenIterable[S]): Transformed[(T, S)] = { - if (that.isParSeq) newZipped[S](that) - else newZipped[S](mutable.ParArray.fromTraversables(that)) - } - protected def newZippedAllTryParSeq[S, U >: T](that: GenIterable[S], thisElem: U, thatElem: S): Transformed[(U, S)] = { - if (that.isParSeq) newZippedAll(that, thisElem, thatElem) - else newZippedAll(mutable.ParArray.fromTraversables(that), thisElem, thatElem) - } - - /* tasks */ - - protected[this] class Force[U >: T, That](cbf: CanCombineFrom[Coll, U, That], protected[this] val pit: IterableSplitter[T]) - extends Transformer[Combiner[U, That], Force[U, That]] { - var result: Combiner[U, That] = null - def leaf(prev: Option[Combiner[U, That]]) = result = pit.copy2builder[U, That, Combiner[U, That]](reuse(prev, cbf(self.underlying))) - protected[this] def newSubtask(p: IterableSplitter[T]) = new Force(cbf, p) - override def merge(that: Force[U, That]) = result = result combine that.result - } - -} - - - - - - - - - - - diff --git a/src/library/scala/collection/parallel/ParMap.scala b/src/library/scala/collection/parallel/ParMap.scala index 1f27ae830a..9f92e6c1e8 100644 --- a/src/library/scala/collection/parallel/ParMap.scala +++ b/src/library/scala/collection/parallel/ParMap.scala @@ -6,7 +6,8 @@ ** |/ ** \* */ -package scala.collection.parallel +package scala +package collection.parallel import scala.collection.Map import scala.collection.GenMap diff --git a/src/library/scala/collection/parallel/ParMapLike.scala b/src/library/scala/collection/parallel/ParMapLike.scala index 56594bec96..d2b15c727a 100644 --- a/src/library/scala/collection/parallel/ParMapLike.scala +++ b/src/library/scala/collection/parallel/ParMapLike.scala @@ -6,11 +6,8 @@ ** |/ ** \* */ - -package scala.collection.parallel - - - +package scala +package collection.parallel import scala.collection.MapLike import scala.collection.GenMapLike @@ -20,10 +17,6 @@ import scala.annotation.unchecked.uncheckedVariance import scala.collection.generic.IdleSignalling import scala.collection.generic.Signalling - - - - /** A template trait for mutable parallel maps. This trait is to be mixed in * with concrete parallel maps to override the representation type. * @@ -67,7 +60,7 @@ self => i => val iter = s def hasNext = iter.hasNext - def next() = iter.next._1 + def next() = iter.next()._1 def split = { val ss = iter.split.map(keysIterator(_)) ss.foreach { _.signalDelegate = i.signalDelegate } @@ -84,7 +77,7 @@ self => i => val iter = s def hasNext = iter.hasNext - def next() = iter.next._2 + def next() = iter.next()._2 def split = { val ss = iter.split.map(valuesIterator(_)) ss.foreach { _.signalDelegate = i.signalDelegate } @@ -146,15 +139,3 @@ self => // note - should not override toMap (could be mutable) } - - - - - - - - - - - - diff --git a/src/library/scala/collection/parallel/ParSeq.scala b/src/library/scala/collection/parallel/ParSeq.scala index b905d1d41f..2c883ba8fe 100644 --- a/src/library/scala/collection/parallel/ParSeq.scala +++ b/src/library/scala/collection/parallel/ParSeq.scala @@ -6,10 +6,8 @@ ** |/ ** \* */ - -package scala.collection.parallel - - +package scala +package collection.parallel import scala.collection.generic.GenericCompanion import scala.collection.generic.GenericParCompanion @@ -18,9 +16,6 @@ import scala.collection.generic.ParFactory import scala.collection.generic.CanCombineFrom import scala.collection.GenSeq import scala.collection.parallel.mutable.ParArrayCombiner -import scala.collection.parallel.mutable.ParArray - - /** A template trait for parallel sequences. * @@ -47,35 +42,9 @@ trait ParSeq[+T] extends GenSeq[T] override def stringPrefix = getClass.getSimpleName } - object ParSeq extends ParFactory[ParSeq] { implicit def canBuildFrom[T]: CanCombineFrom[Coll, T, ParSeq[T]] = new GenericCanCombineFrom[T] def newBuilder[T]: Combiner[T, ParSeq[T]] = ParArrayCombiner[T] - def newCombiner[T]: Combiner[T, ParSeq[T]] = ParArrayCombiner[T] - } - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/library/scala/collection/parallel/ParSeqLike.scala b/src/library/scala/collection/parallel/ParSeqLike.scala index da9abfcf5c..0b6fec364e 100644 --- a/src/library/scala/collection/parallel/ParSeqLike.scala +++ b/src/library/scala/collection/parallel/ParSeqLike.scala @@ -6,7 +6,8 @@ ** |/ ** \* */ -package scala.collection.parallel +package scala +package collection.parallel import scala.collection.{ Parallel, SeqLike, GenSeqLike, GenSeq, GenIterable, Iterator } import scala.collection.generic.DefaultSignalling @@ -15,6 +16,7 @@ import scala.collection.generic.CanBuildFrom import scala.collection.generic.CanCombineFrom import scala.collection.generic.VolatileAbort +import scala.collection.parallel.ParallelCollectionImplicits._ /** A template trait for sequences of type `ParSeq[T]`, representing * parallel sequences with element type `T`. @@ -44,7 +46,7 @@ trait ParSeqLike[+T, +Repr <: ParSeq[T], +Sequential <: Seq[T] with SeqLike[T, S extends scala.collection.GenSeqLike[T, Repr] with ParIterableLike[T, Repr, Sequential] { self => - + protected[this] type SuperParIterator = IterableSplitter[T] /** A more refined version of the iterator found in the `ParallelIterable` trait, @@ -68,7 +70,7 @@ self => val x = self(i) i += 1 x - } else Iterator.empty.next + } else Iterator.empty.next() def head = self(i) @@ -228,7 +230,7 @@ self => b ++= pits(0) b ++= patch b ++= pits(2) - setTaskSupport(b.result, tasksupport) + setTaskSupport(b.result(), tasksupport) } def updated[U >: T, That](index: Int, elem: U)(implicit bf: CanBuildFrom[Repr, U, That]): That = if (bf(repr).isCombiner) { @@ -252,7 +254,7 @@ self => def padTo[U >: T, That](len: Int, elem: U)(implicit bf: CanBuildFrom[Repr, U, That]): That = if (length < len) { patch(length, new immutable.Repetition(elem, len - length), 0) - } else patch(length, Nil, 0); + } else patch(length, Nil, 0) override def zip[U >: T, S, That](that: GenIterable[S])(implicit bf: CanBuildFrom[Repr, (U, S), That]): That = if (bf(repr).isCombiner && that.isParSeq) { val thatseq = that.asParSeq @@ -260,7 +262,7 @@ self => new Zip(length min thatseq.length, combinerFactory(() => bf(repr).asCombiner), splitter, thatseq.splitter) mapResult { _.resultWithTaskSupport } - ); + ) } else super.zip(that)(bf) /** Tests whether every element of this $coll relates to the @@ -322,15 +324,8 @@ self => override def toSeq = this.asInstanceOf[ParSeq[T]] - override def view = new ParSeqView[T, Repr, Sequential] { - protected lazy val underlying = self.repr - protected[this] def viewIdentifier = "" - protected[this] def viewIdString = "" - def length = self.length - def apply(idx: Int) = self(idx) - override def seq = self.seq.view - def splitter = self.splitter - } + @deprecated("use .seq.view", "2.11.0") + override def view = seq.view /* tasks */ @@ -423,7 +418,7 @@ self => @volatile var result: Boolean = true def leaf(prev: Option[Boolean]) = if (!pit.isAborted) { result = pit.sameElements(otherpit) - if (!result) pit.abort + if (!result) pit.abort() } protected[this] def newSubtask(p: SuperParIterator) = unsupported override def split = { @@ -471,7 +466,7 @@ self => @volatile var result: Boolean = true def leaf(prev: Option[Boolean]) = if (!pit.isAborted) { result = pit.corresponds(corr)(otherpit) - if (!result) pit.abort + if (!result) pit.abort() } protected[this] def newSubtask(p: SuperParIterator) = unsupported override def split = { diff --git a/src/library/scala/collection/parallel/ParSeqView.scala b/src/library/scala/collection/parallel/ParSeqView.scala deleted file mode 100644 index 3e3c497352..0000000000 --- a/src/library/scala/collection/parallel/ParSeqView.scala +++ /dev/null @@ -1,46 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - -package scala.collection.parallel - -import scala.collection.{ TraversableView, SeqView, Parallel, Iterator } -import scala.collection.generic.CanCombineFrom - -/** A template view of a non-strict view of a parallel sequence. - * - * @tparam T the type of elements in this parallel sequence - * @tparam Coll the type of the underlying parallel collection - * @tparam CollSeq the type of the sequential collection corresponding to the underlying parallel collection - * - * @since 2.9 - */ -trait ParSeqView[+T, +Coll <: Parallel, +CollSeq] -extends ParSeqViewLike[T, Coll, CollSeq, ParSeqView[T, Coll, CollSeq], SeqView[T, CollSeq]] - - -object ParSeqView { - abstract class NoCombiner[T] extends Combiner[T, Nothing] { -// self: EnvironmentPassingCombiner[T, Nothing] => - def +=(elem: T): this.type = this - def iterator: Iterator[T] = Iterator.empty - def result() = throw new UnsupportedOperationException("ParSeqView.Combiner.result") - def size = throw new UnsupportedOperationException("ParSeqView.Combiner.size") - def clear() {} - def combine[N <: T, NewTo >: Nothing](other: Combiner[N, NewTo]) = - throw new UnsupportedOperationException("ParSeqView.Combiner.result") - } - - type Coll = ParSeqView[_, C, _] forSome { type C <: ParSeq[_] } - - implicit def canBuildFrom[T]: CanCombineFrom[Coll, T, ParSeqView[T, ParSeq[T], Seq[T]]] = - new CanCombineFrom[Coll, T, ParSeqView[T, ParSeq[T], Seq[T]]] { - def apply(from: Coll) = new NoCombiner[T] {} // was: with EnvironmentPassingCombiner[T, Nothing] - def apply() = new NoCombiner[T] {} // was: with EnvironmentPassingCombiner[T, Nothing] - } -} diff --git a/src/library/scala/collection/parallel/ParSeqViewLike.scala b/src/library/scala/collection/parallel/ParSeqViewLike.scala deleted file mode 100644 index 04369d8fde..0000000000 --- a/src/library/scala/collection/parallel/ParSeqViewLike.scala +++ /dev/null @@ -1,188 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala.collection.parallel - -import scala.collection.{ Parallel, SeqView, SeqViewLike, GenSeqView, GenSeqViewLike, GenSeq } -import scala.collection.{ GenIterable, GenTraversable, GenTraversableOnce, Iterator } -import scala.collection.generic.{ CanBuildFrom, SliceInterval } -import scala.collection.generic.CanCombineFrom -import scala.collection.parallel.immutable.ParRange - - -/** A template view of a non-strict view of parallel sequence. - * - * @tparam T the type of the elements in this view - * @tparam Coll type of the collection this view is derived from - * @tparam CollSeq type of the sequential collection corresponding to the underlying parallel collection - * @tparam This actual representation type of this view - * @tparam ThisSeq type of the sequential version of this view - * - * @since 2.9 - */ -trait ParSeqViewLike[+T, - +Coll <: Parallel, - +CollSeq, - +This <: ParSeqView[T, Coll, CollSeq] with ParSeqViewLike[T, Coll, CollSeq, This, ThisSeq], - +ThisSeq <: SeqView[T, CollSeq] with SeqViewLike[T, CollSeq, ThisSeq]] -extends GenSeqView[T, Coll] - with GenSeqViewLike[T, Coll, This] - with ParIterableView[T, Coll, CollSeq] - with ParIterableViewLike[T, Coll, CollSeq, This, ThisSeq] - with ParSeq[T] - with ParSeqLike[T, This, ThisSeq] -{ -self => - - trait Transformed[+S] extends ParSeqView[S, Coll, CollSeq] - with super[ParIterableView].Transformed[S] with super[GenSeqViewLike].Transformed[S] { - override def splitter: SeqSplitter[S] - override def iterator = splitter - override def size = length - } - - trait Sliced extends super[GenSeqViewLike].Sliced with super[ParIterableViewLike].Sliced with Transformed[T] { - // override def slice(from1: Int, until1: Int): This = newSliced(from1 max 0, until1 max 0).asInstanceOf[This] - override def splitter = self.splitter.psplit(from, until - from)(1) - override def seq = self.seq.slice(from, until) - } - - trait Mapped[S] extends super[GenSeqViewLike].Mapped[S] with super[ParIterableViewLike].Mapped[S] with Transformed[S] { - override def splitter = self.splitter.map(mapping) - override def seq = self.seq.map(mapping).asInstanceOf[SeqView[S, CollSeq]] - } - - trait Appended[U >: T] extends super[GenSeqViewLike].Appended[U] with super[ParIterableViewLike].Appended[U] with Transformed[U] { - override def restPar: ParSeq[U] = rest.asParSeq - override def splitter = self.splitter.appendParSeq[U, SeqSplitter[U]](restPar.splitter) - override def seq = self.seq.++(rest).asInstanceOf[SeqView[U, CollSeq]] - } - - trait Forced[S] extends super[GenSeqViewLike].Forced[S] with super[ParIterableViewLike].Forced[S] with Transformed[S] { - override def forcedPar: ParSeq[S] = forced.asParSeq - override def splitter: SeqSplitter[S] = forcedPar.splitter - override def seq = forcedPar.seq.view.asInstanceOf[SeqView[S, CollSeq]] - } - - trait Zipped[S] extends super[GenSeqViewLike].Zipped[S] with super[ParIterableViewLike].Zipped[S] with Transformed[(T, S)] { - override def splitter = self.splitter zipParSeq otherPar.splitter - override def seq = (self.seq zip other).asInstanceOf[SeqView[(T, S), CollSeq]] - } - - trait ZippedAll[U >: T, S] extends super[GenSeqViewLike].ZippedAll[U, S] with super[ParIterableViewLike].ZippedAll[U, S] with Transformed[(U, S)] { - override def splitter: SeqSplitter[(U, S)] = self.splitter.zipAllParSeq(otherPar.splitter, thisElem, thatElem) - override def seq = (self.seq.zipAll(other, thisElem, thatElem)).asInstanceOf[SeqView[(U, S), CollSeq]] - } - - trait Reversed extends super.Reversed with Transformed[T] { - override def splitter: SeqSplitter[T] = self.splitter.reverse - override def seq = self.seq.reverse.asInstanceOf[SeqView[T, CollSeq]] - } - - // use only with ParSeq patches, otherwise force - trait Patched[U >: T] extends super.Patched[U] with Transformed[U] { - def patchPar: ParSeq[U] = patch.asInstanceOf[ParSeq[U]] - override def splitter: SeqSplitter[U] = self.splitter.patchParSeq[U](from, patchPar.splitter, replaced) - override def seq = self.seq.patch(from, patch, replaced).asInstanceOf[SeqView[U, CollSeq]] - } - - // !!! - // - // What is up with this trait and method, why are they here doing - // nothing but throwing exceptions, without even being deprecated? - // They're not implementing something abstract; why aren't they - // just removed? - // - // use Patched instead - trait Prepended[U >: T] extends super.Prepended[U] with Transformed[U] { - unsupported - } - protected def newPrepended[U >: T](elem: U): Transformed[U] = unsupported - - /* wrapper virtual ctors */ - - protected override def newSliced(_endpoints: SliceInterval): Transformed[T] = new { val endpoints = _endpoints } with Sliced - protected override def newAppended[U >: T](that: GenTraversable[U]): Transformed[U] = { - // we only append if `that` is a parallel sequence, i.e. it has a precise splitter - if (that.isParSeq) new Appended[U] { val rest = that } - else newForced(mutable.ParArray.fromTraversables(this, that)) - } - protected override def newForced[S](xs: => GenSeq[S]): Transformed[S] = { - if (xs.isParSeq) new Forced[S] { val forced = xs } - else new Forced[S] { val forced = mutable.ParArray.fromTraversables(xs) } - } - protected override def newMapped[S](f: T => S): Transformed[S] = new Mapped[S] { val mapping = f } - protected override def newZipped[S](that: GenIterable[S]): Transformed[(T, S)] = new Zipped[S] { val other = that } - protected override def newZippedAll[U >: T, S](that: GenIterable[S], _thisElem: U, _thatElem: S): Transformed[(U, S)] = new ZippedAll[U, S] { - val other = that - val thisElem = _thisElem - val thatElem = _thatElem - } - protected def newReversed: Transformed[T] = new Reversed { } - protected def newPatched[U >: T](_from: Int, _patch: GenSeq[U], _replaced: Int): Transformed[U] = new { - val from = _from; - val patch = _patch; - val replaced = _replaced - } with Patched[U] - - /* operation overrides */ - - /* sliced */ - override def slice(from: Int, until: Int): This = newSliced(SliceInterval(from, until)).asInstanceOf[This] - override def take(n: Int): This = newSliced(SliceInterval(0, n)).asInstanceOf[This] - override def drop(n: Int): This = newSliced(SliceInterval(n, length)).asInstanceOf[This] - override def splitAt(n: Int): (This, This) = (take(n), drop(n)) - - /* appended */ - override def ++[U >: T, That](xs: GenTraversableOnce[U])(implicit bf: CanBuildFrom[This, U, That]): That = newAppended(xs.toTraversable).asInstanceOf[That] - override def :+[U >: T, That](elem: U)(implicit bf: CanBuildFrom[This, U, That]): That = ++(Iterator.single(elem))(bf) - //override def union[U >: T, That](that: GenSeq[U])(implicit bf: CanBuildFrom[This, U, That]): That = this ++ that - - /* misc */ - override def map[S, That](f: T => S)(implicit bf: CanBuildFrom[This, S, That]): That = newMapped(f).asInstanceOf[That] - override def zip[U >: T, S, That](that: GenIterable[S])(implicit bf: CanBuildFrom[This, (U, S), That]): That = newZippedTryParSeq(that).asInstanceOf[That] - override def zipWithIndex[U >: T, That](implicit bf: CanBuildFrom[This, (U, Int), That]): That = - newZipped(ParRange(0, splitter.remaining, 1, false)).asInstanceOf[That] - override def reverse: This = newReversed.asInstanceOf[This] - override def reverseMap[S, That](f: T => S)(implicit bf: CanBuildFrom[This, S, That]): That = reverse.map(f) - - /* patched */ - override def updated[U >: T, That](index: Int, elem: U)(implicit bf: CanBuildFrom[This, U, That]): That = { - require(0 <= index && index < length) - patch(index, List(elem), 1)(bf) - } - override def padTo[U >: T, That](len: Int, elem: U)(implicit bf: CanBuildFrom[This, U, That]): That = patch(length, Seq.fill(len - length)(elem), 0) - override def +:[U >: T, That](elem: U)(implicit bf: CanBuildFrom[This, U, That]): That = patch(0, mutable.ParArray.fromTraversables(Iterator.single(elem)), 0) - override def patch[U >: T, That](from: Int, patch: GenSeq[U], replace: Int)(implicit bf: CanBuildFrom[This, U, That]): That = newPatched(from, patch, replace).asInstanceOf[That] - - /* forced */ - // override def diff[U >: T](that: GenSeq[U]): This = newForced(thisParSeq diff that).asInstanceOf[This] - // override def intersect[U >: T](that: GenSeq[U]): This = newForced(thisParSeq intersect that).asInstanceOf[This] - // override def sorted[U >: T](implicit ord: Ordering[U]): This = newForced(thisParSeq sorted ord).asInstanceOf[This] - override def collect[S, That](pf: PartialFunction[T, S])(implicit bf: CanBuildFrom[This, S, That]): That = filter(pf.isDefinedAt).map(pf)(bf) - override def scanLeft[S, That](z: S)(op: (S, T) => S)(implicit bf: CanBuildFrom[This, S, That]): That = newForced(thisParSeq.scanLeft(z)(op)).asInstanceOf[That] - override def scanRight[S, That](z: S)(op: (T, S) => S)(implicit bf: CanBuildFrom[This, S, That]): That = newForced(thisParSeq.scanRight(z)(op)).asInstanceOf[That] - override def groupBy[K](f: T => K): immutable.ParMap[K, This] = thisParSeq.groupBy(f).map(kv => (kv._1, newForced(kv._2).asInstanceOf[This])) - override def force[U >: T, That](implicit bf: CanBuildFrom[Coll, U, That]) = bf ifParallel { pbf => - tasksupport.executeAndWaitResult(new Force(pbf, splitter).mapResult(_.result).asInstanceOf[Task[That, _]]) - } otherwise { - val b = bf(underlying) - b ++= this.iterator - b.result - } - - /* tasks */ - - protected[this] class Force[U >: T, That](cbf: CanCombineFrom[Coll, U, That], protected[this] val pit: SeqSplitter[T]) - extends Transformer[Combiner[U, That], Force[U, That]] { - var result: Combiner[U, That] = null - def leaf(prev: Option[Combiner[U, That]]) = result = pit.copy2builder[U, That, Combiner[U, That]](reuse(prev, cbf(self.underlying))) - protected[this] def newSubtask(p: SuperParIterator) = new Force(cbf, down(p)) - override def merge(that: Force[U, That]) = result = result combine that.result - } -} diff --git a/src/library/scala/collection/parallel/ParSet.scala b/src/library/scala/collection/parallel/ParSet.scala index 6e5e9b4387..ba3d23f0e4 100644 --- a/src/library/scala/collection/parallel/ParSet.scala +++ b/src/library/scala/collection/parallel/ParSet.scala @@ -6,25 +6,12 @@ ** |/ ** \* */ +package scala +package collection +package parallel -package scala.collection.parallel - - - - - - - -import scala.collection.Set -import scala.collection.GenSet -import scala.collection.mutable.Builder import scala.collection.generic._ - - - - - /** A template trait for parallel sets. * * $sideeffects @@ -35,12 +22,12 @@ import scala.collection.generic._ * @since 2.9 */ trait ParSet[T] -extends GenSet[T] + extends GenSet[T] with GenericParTemplate[T, ParSet] with ParIterable[T] with ParSetLike[T, ParSet[T], Set[T]] -{ -self => +{ self => + override def empty: ParSet[T] = mutable.ParHashSet[T]() //protected[this] override def newCombiner: Combiner[T, ParSet[T]] = ParSet.newCombiner[T] @@ -50,39 +37,8 @@ self => override def stringPrefix = "ParSet" } - - object ParSet extends ParSetFactory[ParSet] { def newCombiner[T]: Combiner[T, ParSet[T]] = mutable.ParHashSetCombiner[T] implicit def canBuildFrom[T]: CanCombineFrom[Coll, T, ParSet[T]] = new GenericCanCombineFrom[T] } - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/library/scala/collection/parallel/ParSetLike.scala b/src/library/scala/collection/parallel/ParSetLike.scala index c80b5ded26..4e9a2e5751 100644 --- a/src/library/scala/collection/parallel/ParSetLike.scala +++ b/src/library/scala/collection/parallel/ParSetLike.scala @@ -6,23 +6,13 @@ ** |/ ** \* */ - -package scala.collection.parallel - - +package scala +package collection.parallel import scala.collection.SetLike import scala.collection.GenSetLike import scala.collection.GenSet import scala.collection.Set -import scala.collection.mutable.Builder - - - - - - - /** A template trait for parallel sets. This trait is mixed in with concrete * parallel sets to override the representation type. @@ -52,26 +42,4 @@ extends GenSetLike[T, Repr] def diff(that: GenSet[T]): Repr = sequentially { _ diff that } - } - - - - - - - - - - - - - - - - - - - - - diff --git a/src/library/scala/collection/parallel/PreciseSplitter.scala b/src/library/scala/collection/parallel/PreciseSplitter.scala index 42563f4dc9..4b22934a29 100644 --- a/src/library/scala/collection/parallel/PreciseSplitter.scala +++ b/src/library/scala/collection/parallel/PreciseSplitter.scala @@ -6,12 +6,11 @@ ** |/ ** \* */ -package scala.collection.parallel - +package scala +package collection.parallel import scala.collection.Seq - /** A precise splitter (or a precise split iterator) can be split into arbitrary number of splitters * that traverse disjoint subsets of arbitrary sizes. * @@ -55,10 +54,4 @@ trait PreciseSplitter[+T] extends Splitter[T] { def psplit(sizes: Int*): Seq[PreciseSplitter[T]] def split: Seq[PreciseSplitter[T]] - } - - - - - diff --git a/src/library/scala/collection/parallel/RemainsIterator.scala b/src/library/scala/collection/parallel/RemainsIterator.scala index 3150b0d763..5f2ceac0e0 100644 --- a/src/library/scala/collection/parallel/RemainsIterator.scala +++ b/src/library/scala/collection/parallel/RemainsIterator.scala @@ -6,10 +6,8 @@ ** |/ ** \* */ - -package scala.collection.parallel - - +package scala +package collection.parallel import scala.collection.Parallel import scala.collection.generic.Signalling @@ -21,8 +19,6 @@ import scala.collection.Iterator.empty import scala.collection.GenTraversableOnce import scala.collection.parallel.immutable.repetition - - private[collection] trait RemainsIterator[+T] extends Iterator[T] { /** The number of elements this iterator has yet to iterate. * This method doesn't change the state of the iterator. @@ -35,7 +31,6 @@ private[collection] trait RemainsIterator[+T] extends Iterator[T] { def isRemainingCheap = true } - /** Augments iterators with additional methods, mostly transformers, * assuming they iterate an iterable collection. * @@ -47,47 +42,47 @@ private[collection] trait AugmentedIterableIterator[+T] extends RemainsIterator[ override def count(p: T => Boolean): Int = { var i = 0 - while (hasNext) if (p(next)) i += 1 + while (hasNext) if (p(next())) i += 1 i } override def reduce[U >: T](op: (U, U) => U): U = { - var r: U = next - while (hasNext) r = op(r, next) + var r: U = next() + while (hasNext) r = op(r, next()) r } override def fold[U >: T](z: U)(op: (U, U) => U): U = { var r = z - while (hasNext) r = op(r, next) + while (hasNext) r = op(r, next()) r } override def sum[U >: T](implicit num: Numeric[U]): U = { var r: U = num.zero - while (hasNext) r = num.plus(r, next) + while (hasNext) r = num.plus(r, next()) r } override def product[U >: T](implicit num: Numeric[U]): U = { var r: U = num.one - while (hasNext) r = num.times(r, next) + while (hasNext) r = num.times(r, next()) r } override def min[U >: T](implicit ord: Ordering[U]): T = { - var r = next + var r = next() while (hasNext) { - val curr = next + val curr = next() if (ord.lteq(curr, r)) r = curr } r } override def max[U >: T](implicit ord: Ordering[U]): T = { - var r = next + var r = next() while (hasNext) { - val curr = next + val curr = next() if (ord.gteq(curr, r)) r = curr } r @@ -97,16 +92,16 @@ private[collection] trait AugmentedIterableIterator[+T] extends RemainsIterator[ var i = from val until = from + len while (i < until && hasNext) { - array(i) = next + array(i) = next() i += 1 } } def reduceLeft[U >: T](howmany: Int, op: (U, U) => U): U = { var i = howmany - 1 - var u: U = next + var u: U = next() while (i > 0 && hasNext) { - u = op(u, next) + u = op(u, next()) i -= 1 } u @@ -117,15 +112,16 @@ private[collection] trait AugmentedIterableIterator[+T] extends RemainsIterator[ def map2combiner[S, That](f: T => S, cb: Combiner[S, That]): Combiner[S, That] = { //val cb = pbf(repr) if (isRemainingCheap) cb.sizeHint(remaining) - while (hasNext) cb += f(next) + while (hasNext) cb += f(next()) cb } def collect2combiner[S, That](pf: PartialFunction[T, S], cb: Combiner[S, That]): Combiner[S, That] = { //val cb = pbf(repr) + val runWith = pf.runWith(cb += _) while (hasNext) { - val curr = next - if (pf.isDefinedAt(curr)) cb += pf(curr) + val curr = next() + runWith(curr) } cb } @@ -133,7 +129,7 @@ private[collection] trait AugmentedIterableIterator[+T] extends RemainsIterator[ def flatmap2combiner[S, That](f: T => GenTraversableOnce[S], cb: Combiner[S, That]): Combiner[S, That] = { //val cb = pbf(repr) while (hasNext) { - val traversable = f(next).seq + val traversable = f(next()).seq if (traversable.isInstanceOf[Iterable[_]]) cb ++= traversable.asInstanceOf[Iterable[S]].iterator else cb ++= traversable } @@ -148,7 +144,7 @@ private[collection] trait AugmentedIterableIterator[+T] extends RemainsIterator[ def filter2combiner[U >: T, This](pred: T => Boolean, cb: Combiner[U, This]): Combiner[U, This] = { while (hasNext) { - val curr = next + val curr = next() if (pred(curr)) cb += curr } cb @@ -156,7 +152,7 @@ private[collection] trait AugmentedIterableIterator[+T] extends RemainsIterator[ def filterNot2combiner[U >: T, This](pred: T => Boolean, cb: Combiner[U, This]): Combiner[U, This] = { while (hasNext) { - val curr = next + val curr = next() if (!pred(curr)) cb += curr } cb @@ -164,7 +160,7 @@ private[collection] trait AugmentedIterableIterator[+T] extends RemainsIterator[ def partition2combiners[U >: T, This](pred: T => Boolean, btrue: Combiner[U, This], bfalse: Combiner[U, This]) = { while (hasNext) { - val curr = next + val curr = next() if (pred(curr)) btrue += curr else bfalse += curr } @@ -214,7 +210,7 @@ private[collection] trait AugmentedIterableIterator[+T] extends RemainsIterator[ def takeWhile2combiner[U >: T, This](p: T => Boolean, cb: Combiner[U, This]) = { var loop = true while (hasNext && loop) { - val curr = next + val curr = next() if (p(curr)) cb += curr else loop = false } @@ -224,7 +220,7 @@ private[collection] trait AugmentedIterableIterator[+T] extends RemainsIterator[ def span2combiners[U >: T, This](p: T => Boolean, before: Combiner[U, This], after: Combiner[U, This]) = { var isBefore = true while (hasNext && isBefore) { - val curr = next + val curr = next() if (p(curr)) before += curr else { if (isRemainingCheap) after.sizeHint(remaining + 1) @@ -240,7 +236,7 @@ private[collection] trait AugmentedIterableIterator[+T] extends RemainsIterator[ var last = z var i = from while (hasNext) { - last = op(last, next) + last = op(last, next()) array(i) = last i += 1 } @@ -249,7 +245,7 @@ private[collection] trait AugmentedIterableIterator[+T] extends RemainsIterator[ def scanToCombiner[U >: T, That](startValue: U, op: (U, U) => U, cb: Combiner[U, That]) = { var curr = startValue while (hasNext) { - curr = op(curr, next) + curr = op(curr, next()) cb += curr } cb @@ -259,7 +255,7 @@ private[collection] trait AugmentedIterableIterator[+T] extends RemainsIterator[ var curr = startValue var left = howmany while (left > 0) { - curr = op(curr, next) + curr = op(curr, next()) cb += curr left -= 1 } @@ -269,16 +265,16 @@ private[collection] trait AugmentedIterableIterator[+T] extends RemainsIterator[ def zip2combiner[U >: T, S, That](otherpit: RemainsIterator[S], cb: Combiner[(U, S), That]): Combiner[(U, S), That] = { if (isRemainingCheap && otherpit.isRemainingCheap) cb.sizeHint(remaining min otherpit.remaining) while (hasNext && otherpit.hasNext) { - cb += ((next, otherpit.next)) + cb += ((next(), otherpit.next())) } cb } def zipAll2combiner[U >: T, S, That](that: RemainsIterator[S], thiselem: U, thatelem: S, cb: Combiner[(U, S), That]): Combiner[(U, S), That] = { if (isRemainingCheap && that.isRemainingCheap) cb.sizeHint(remaining max that.remaining) - while (this.hasNext && that.hasNext) cb += ((this.next, that.next)) - while (this.hasNext) cb += ((this.next, thatelem)) - while (that.hasNext) cb += ((thiselem, that.next)) + while (this.hasNext && that.hasNext) cb += ((this.next(), that.next())) + while (this.hasNext) cb += ((this.next(), thatelem)) + while (that.hasNext) cb += ((thiselem, that.next())) cb } @@ -298,7 +294,7 @@ private[collection] trait AugmentedSeqIterator[+T] extends AugmentedIterableIter var total = 0 var loop = true while (hasNext && loop) { - if (pred(next)) total += 1 + if (pred(next())) total += 1 else loop = false } total @@ -308,7 +304,7 @@ private[collection] trait AugmentedSeqIterator[+T] extends AugmentedIterableIter var i = 0 var loop = true while (hasNext && loop) { - if (pred(next)) loop = false + if (pred(next())) loop = false else i += 1 } if (loop) -1 else i @@ -318,7 +314,7 @@ private[collection] trait AugmentedSeqIterator[+T] extends AugmentedIterableIter var pos = -1 var i = 0 while (hasNext) { - if (pred(next)) pos = i + if (pred(next())) pos = i i += 1 } pos @@ -326,7 +322,7 @@ private[collection] trait AugmentedSeqIterator[+T] extends AugmentedIterableIter def corresponds[S](corr: (T, S) => Boolean)(that: Iterator[S]): Boolean = { while (hasNext && that.hasNext) { - if (!corr(next, that.next)) return false + if (!corr(next(), that.next())) return false } hasNext == that.hasNext } @@ -348,7 +344,7 @@ private[collection] trait AugmentedSeqIterator[+T] extends AugmentedIterableIter //val cb = cbf(repr) if (isRemainingCheap) cb.sizeHint(remaining) var lst = List[S]() - while (hasNext) lst ::= f(next) + while (hasNext) lst ::= f(next()) while (lst != Nil) { cb += lst.head lst = lst.tail @@ -363,7 +359,7 @@ private[collection] trait AugmentedSeqIterator[+T] extends AugmentedIterableIter while (hasNext) { if (j == index) { cb += elem - next + next() } else cb += next j += 1 } @@ -438,7 +434,7 @@ self => class Taken(taken: Int) extends IterableSplitter[T] { var remaining = taken min self.remaining def hasNext = remaining > 0 - def next = { remaining -= 1; self.next } + def next = { remaining -= 1; self.next() } def dup: IterableSplitter[T] = self.dup.take(taken) def split: Seq[IterableSplitter[T]] = takeSeq(self.split) { (p, n) => p.take(n) } protected[this] def takeSeq[PI <: IterableSplitter[T]](sq: Seq[PI])(taker: (PI, Int) => PI) = { @@ -466,7 +462,7 @@ self => class Mapped[S](f: T => S) extends IterableSplitter[S] { signalDelegate = self.signalDelegate def hasNext = self.hasNext - def next = f(self.next) + def next = f(self.next()) def remaining = self.remaining def dup: IterableSplitter[S] = self.dup map f def split: Seq[IterableSplitter[S]] = self.split.map { _ map f } @@ -483,8 +479,8 @@ self => } else false def next = if (curr eq self) { hasNext - curr.next - } else curr.next + curr.next() + } else curr.next() def remaining = if (curr eq self) curr.remaining + that.remaining else curr.remaining protected def firstNonEmpty = (curr eq self) && curr.hasNext def dup: IterableSplitter[U] = self.dup.appendParIterable[U, PI](that) @@ -496,7 +492,7 @@ self => class Zipped[S](protected val that: SeqSplitter[S]) extends IterableSplitter[(T, S)] { signalDelegate = self.signalDelegate def hasNext = self.hasNext && that.hasNext - def next = (self.next, that.next) + def next = (self.next(), that.next()) def remaining = self.remaining min that.remaining def dup: IterableSplitter[(T, S)] = self.dup.zipParSeq(that) def split: Seq[IterableSplitter[(T, S)]] = { @@ -514,9 +510,10 @@ self => signalDelegate = self.signalDelegate def hasNext = self.hasNext || that.hasNext def next = if (self.hasNext) { - if (that.hasNext) (self.next, that.next) - else (self.next, thatelem) - } else (thiselem, that.next); + if (that.hasNext) (self.next(), that.next()) + else (self.next(), thatelem) + } else (thiselem, that.next()) + def remaining = self.remaining max that.remaining def dup: IterableSplitter[(U, S)] = self.dup.zipAllParSeq(that, thiselem, thatelem) def split: Seq[IterableSplitter[(U, S)]] = { @@ -530,10 +527,8 @@ self => } def zipAllParSeq[S, U >: T, R >: S](that: SeqSplitter[S], thisElem: U, thatElem: R) = new ZippedAll[U, R](that, thisElem, thatElem) - } - /** Parallel sequence iterators allow splitting into arbitrary subsets. * * @tparam T type of the elements iterated. @@ -605,7 +600,7 @@ self => } else Seq(sz) } val (selfszfrom, thatszfrom) = splitsizes.zip(szcum.init).span(_._2 < selfrem) - val (selfsizes, thatsizes) = (selfszfrom map { _._1 }, thatszfrom map { _._1 }); + val (selfsizes, thatsizes) = (selfszfrom map { _._1 }, thatszfrom map { _._1 }) // split iterators val selfs = self.psplit(selfsizes: _*) @@ -674,37 +669,3 @@ self => def patchParSeq[U >: T](from: Int, patchElems: SeqSplitter[U], replaced: Int) = new Patched(from, patchElems, replaced) } - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/library/scala/collection/parallel/Splitter.scala b/src/library/scala/collection/parallel/Splitter.scala index dc49bcf9d7..8329f15d88 100644 --- a/src/library/scala/collection/parallel/Splitter.scala +++ b/src/library/scala/collection/parallel/Splitter.scala @@ -6,7 +6,8 @@ ** |/ ** \* */ -package scala.collection.parallel +package scala +package collection.parallel import scala.collection.{ Seq, Iterator } @@ -52,7 +53,7 @@ trait Splitter[+T] extends Iterator[T] { object Splitter { def empty[T]: Splitter[T] = new Splitter[T] { def hasNext = false - def next = Iterator.empty.next + def next = Iterator.empty.next() def split = Seq(this) } } diff --git a/src/library/scala/collection/parallel/TaskSupport.scala b/src/library/scala/collection/parallel/TaskSupport.scala index 9bed5be51b..9064018d46 100644 --- a/src/library/scala/collection/parallel/TaskSupport.scala +++ b/src/library/scala/collection/parallel/TaskSupport.scala @@ -6,39 +6,32 @@ ** |/ ** \* */ - -package scala.collection.parallel - - +package scala +package collection.parallel import java.util.concurrent.ThreadPoolExecutor import scala.concurrent.forkjoin.ForkJoinPool import scala.concurrent.ExecutionContext - - -/** A trait implementing the scheduling of - * a parallel collection operation. +/** A trait implementing the scheduling of a parallel collection operation. * * Parallel collections are modular in the way operations are scheduled. Each * parallel collection is parametrized with a task support object which is * responsible for scheduling and load-balancing tasks to processors. - * + * * A task support object can be changed in a parallel collection after it has * been created, but only during a quiescent period, i.e. while there are no * concurrent invocations to parallel collection methods. * * There are currently a few task support implementations available for * parallel collections. The [[scala.collection.parallel.ForkJoinTaskSupport]] - * uses a fork-join pool - * internally and is used by default on JVM 1.6 or greater. The less efficient - * [[scala.collection.parallel.ThreadPoolTaskSupport]] is a fallback for JVM - * 1.5 and JVMs that do not support the fork join pools. The - * [[scala.collection.parallel.ExecutionContextTaskSupport]] uses the + * uses a fork-join pool internally. + * + * The [[scala.collection.parallel.ExecutionContextTaskSupport]] uses the * default execution context implementation found in scala.concurrent, and it - * reuses the thread pool used in scala.concurrent (this is either a fork join - * pool or a thread pool executor, depending on the JVM version). The - * execution context task support is set to each parallel collection by + * reuses the thread pool used in scala.concurrent. + * + * The execution context task support is set to each parallel collection by * default, so parallel collections reuse the same fork-join pool as the * future API. * @@ -56,7 +49,6 @@ import scala.concurrent.ExecutionContext */ trait TaskSupport extends Tasks - /** A task support that uses a fork join pool to schedule tasks. * * @see [[scala.collection.parallel.TaskSupport]] for more information. @@ -68,17 +60,17 @@ extends TaskSupport with AdaptiveWorkStealingForkJoinTasks * * @see [[scala.collection.parallel.TaskSupport]] for more information. */ +@deprecated("Use `ForkJoinTaskSupport` instead.", "2.11.0") class ThreadPoolTaskSupport(val environment: ThreadPoolExecutor = ThreadPoolTasks.defaultThreadPool) extends TaskSupport with AdaptiveWorkStealingThreadPoolTasks - /** A task support that uses an execution context to schedule tasks. - * + * * It can be used with the default execution context implementation in the * `scala.concurrent` package. It internally forwards the call to either a * forkjoin based task support or a thread pool executor one, depending on * what the execution context uses. - * + * * By default, parallel collections are parametrized with this task support * object, so parallel collections share the same execution context backend * as the rest of the `scala.concurrent` package. @@ -87,22 +79,3 @@ extends TaskSupport with AdaptiveWorkStealingThreadPoolTasks */ class ExecutionContextTaskSupport(val environment: ExecutionContext = scala.concurrent.ExecutionContext.global) extends TaskSupport with ExecutionContextTasks - - - - - - - - - - - - - - - - - - - diff --git a/src/library/scala/collection/parallel/Tasks.scala b/src/library/scala/collection/parallel/Tasks.scala index cec9e294c1..fcf0dff846 100644 --- a/src/library/scala/collection/parallel/Tasks.scala +++ b/src/library/scala/collection/parallel/Tasks.scala @@ -6,20 +6,15 @@ ** |/ ** \* */ -package scala.collection.parallel - - +package scala +package collection.parallel import java.util.concurrent.ThreadPoolExecutor - import scala.concurrent.forkjoin._ import scala.concurrent.ExecutionContext import scala.util.control.Breaks._ - import scala.annotation.unchecked.uncheckedVariance - - trait Task[R, +Tp] { type Result = R @@ -54,38 +49,30 @@ trait Task[R, +Tp] { leaf(lastres) result = result // ensure that effects of `leaf` are visible to readers of `result` } catchBreak { - signalAbort + signalAbort() } } catch { - case thr: Exception => + case thr: Throwable => result = result // ensure that effects of `leaf` are visible throwable = thr - signalAbort + signalAbort() } } private[parallel] def tryMerge(t: Tp @uncheckedVariance) { val that = t.asInstanceOf[Task[R, Tp]] - val local = result // ensure that any effects of modifying `result` are detected - // checkMerge(that) if (this.throwable == null && that.throwable == null) merge(t) mergeThrowables(that) } - private def checkMerge(that: Task[R, Tp] @uncheckedVariance) { - if (this.throwable == null && that.throwable == null && (this.result == null || that.result == null)) { - println("This: " + this + ", thr=" + this.throwable + "; merged with " + that + ", thr=" + that.throwable) - } else if (this.throwable != null || that.throwable != null) { - println("merging this: " + this + " with thr: " + this.throwable + " with " + that + ", thr=" + that.throwable) - } - } - private[parallel] def mergeThrowables(that: Task[_, _]) { - if (this.throwable != null && that.throwable != null) { - // merge exceptions, since there were multiple exceptions - this.throwable = this.throwable alongWith that.throwable - } else if (that.throwable != null) this.throwable = that.throwable - else this.throwable = this.throwable + // TODO: As soon as we target Java >= 7, use Throwable#addSuppressed + // to pass additional Throwables to the caller, e. g. + // if (this.throwable != null && that.throwable != null) + // this.throwable.addSuppressed(that.throwable) + // For now, we just use whatever Throwable comes across “first”. + if (this.throwable == null && that.throwable != null) + this.throwable = that.throwable } // override in concrete task implementations to signal abort to other tasks @@ -176,7 +163,6 @@ trait AdaptiveWorkStealingTasks extends Tasks { while (last.next != null) { // val lastresult = Option(last.body.result) - val beforelast = last last = last.next if (last.tryCancel()) { // println("Done with " + beforelast.body + ", next direct is " + last.body) @@ -202,7 +188,7 @@ trait AdaptiveWorkStealingTasks extends Tasks { last = t t.start() } - } while (head.body.shouldSplitFurther); + } while (head.body.shouldSplitFurther) head.next = last head } @@ -225,6 +211,7 @@ trait AdaptiveWorkStealingTasks extends Tasks { /** An implementation of tasks objects based on the Java thread pooling API. */ +@deprecated("Use `ForkJoinTasks` instead.", "2.11.0") trait ThreadPoolTasks extends Tasks { import java.util.concurrent._ @@ -313,7 +300,7 @@ trait ThreadPoolTasks extends Tasks { () => { t.sync() - t.body.forwardThrowable + t.body.forwardThrowable() t.body.result } } @@ -325,7 +312,7 @@ trait ThreadPoolTasks extends Tasks { t.start() t.sync() - t.body.forwardThrowable + t.body.forwardThrowable() t.body.result } @@ -333,6 +320,7 @@ trait ThreadPoolTasks extends Tasks { } +@deprecated("Use `ForkJoinTasks` instead.", "2.11.0") object ThreadPoolTasks { import java.util.concurrent._ @@ -357,60 +345,6 @@ object ThreadPoolTasks { ) } - -/** An implementation of tasks objects based on the Java thread pooling API and synchronization using futures. */ -@deprecated("This implementation is not used.", "2.10.0") -trait FutureThreadPoolTasks extends Tasks { - import java.util.concurrent._ - - trait WrappedTask[R, +Tp] extends Runnable with super.WrappedTask[R, Tp] { - @volatile var future: Future[_] = null - - def start() = { - executor.synchronized { - future = executor.submit(this) - } - } - def sync() = future.get - def tryCancel = false - def run = { - compute() - } - } - - protected def newWrappedTask[R, Tp](b: Task[R, Tp]): WrappedTask[R, Tp] - - val environment: AnyRef = FutureThreadPoolTasks.defaultThreadPool - def executor = environment.asInstanceOf[ThreadPoolExecutor] - - def execute[R, Tp](task: Task[R, Tp]): () => R = { - val t = newWrappedTask(task) - - // debuglog("-----------> Executing without wait: " + task) - t.start - - () => { - t.sync - t.body.forwardThrowable - t.body.result - } - } - - def executeAndWaitResult[R, Tp](task: Task[R, Tp]): R = { - val t = newWrappedTask(task) - - // debuglog("-----------> Executing with wait: " + task) - t.start - - t.sync - t.body.forwardThrowable - t.body.result - } - - def parallelismLevel = FutureThreadPoolTasks.numCores - -} - object FutureThreadPoolTasks { import java.util.concurrent._ @@ -467,8 +401,8 @@ trait ForkJoinTasks extends Tasks with HavingForkJoinPool { } () => { - fjtask.sync - fjtask.body.forwardThrowable + fjtask.sync() + fjtask.body.forwardThrowable() fjtask.body.result } } @@ -489,24 +423,19 @@ trait ForkJoinTasks extends Tasks with HavingForkJoinPool { forkJoinPool.execute(fjtask) } - fjtask.sync + fjtask.sync() // if (fjtask.body.throwable != null) println("throwing: " + fjtask.body.throwable + " at " + fjtask.body) - fjtask.body.forwardThrowable + fjtask.body.forwardThrowable() fjtask.body.result } def parallelismLevel = forkJoinPool.getParallelism - } - object ForkJoinTasks { - val defaultForkJoinPool: ForkJoinPool = new ForkJoinPool() // scala.parallel.forkjoinpool - // defaultForkJoinPool.setParallelism(Runtime.getRuntime.availableProcessors) - // defaultForkJoinPool.setMaximumPoolSize(Runtime.getRuntime.availableProcessors) + lazy val defaultForkJoinPool: ForkJoinPool = new ForkJoinPool() } - /* Some boilerplate due to no deep mixin composition. Not sure if it can be done differently without them. */ trait AdaptiveWorkStealingForkJoinTasks extends ForkJoinTasks with AdaptiveWorkStealingTasks { @@ -517,10 +446,9 @@ trait AdaptiveWorkStealingForkJoinTasks extends ForkJoinTasks with AdaptiveWorkS } def newWrappedTask[R, Tp](b: Task[R, Tp]) = new WrappedTask[R, Tp](b) - } - +@deprecated("Use `AdaptiveWorkStealingForkJoinTasks` instead.", "2.11.0") trait AdaptiveWorkStealingThreadPoolTasks extends ThreadPoolTasks with AdaptiveWorkStealingTasks { class WrappedTask[R, Tp](val body: Task[R, Tp]) @@ -529,24 +457,100 @@ trait AdaptiveWorkStealingThreadPoolTasks extends ThreadPoolTasks with AdaptiveW } def newWrappedTask[R, Tp](b: Task[R, Tp]) = new WrappedTask[R, Tp](b) - } +/** An implementation of the `Tasks` that uses Scala `Future`s to compute + * the work encapsulated in each task. + */ +private[parallel] final class FutureTasks(executor: ExecutionContext) extends Tasks { + import scala.concurrent._ + import scala.util._ -trait ExecutionContextTasks extends Tasks { + private val maxdepth = (math.log(parallelismLevel) / math.log(2) + 1).toInt + + val environment: ExecutionContext = executor + + /** Divides this task into a lot of small tasks and executes them asynchronously + * using futures. + * Folds the futures and merges them asynchronously. + */ + private def exec[R, Tp](topLevelTask: Task[R, Tp]): Future[R] = { + implicit val ec = environment + + /** Constructs a tree of futures where tasks can be reasonably split. + */ + def compute(task: Task[R, Tp], depth: Int): Future[Task[R, Tp]] = { + if (task.shouldSplitFurther && depth < maxdepth) { + val subtasks = task.split + val subfutures = for (subtask <- subtasks.iterator) yield compute(subtask, depth + 1) + subfutures.reduceLeft { (firstFuture, nextFuture) => + for { + firstTask <- firstFuture + nextTask <- nextFuture + } yield { + firstTask tryMerge nextTask.repr + firstTask + } + } andThen { + case Success(firstTask) => + task.throwable = firstTask.throwable + task.result = firstTask.result + case Failure(exception) => + task.throwable = exception + } + } else Future { + task.tryLeaf(None) + task + } + } + + compute(topLevelTask, 0) map { t => + t.forwardThrowable() + t.result + } + } + + def execute[R, Tp](task: Task[R, Tp]): () => R = { + val future = exec(task) + val callback = () => { + Await.result(future, scala.concurrent.duration.Duration.Inf) + } + callback + } + + def executeAndWaitResult[R, Tp](task: Task[R, Tp]): R = { + execute(task)() + } + + def parallelismLevel = Runtime.getRuntime.availableProcessors +} +/** This tasks implementation uses execution contexts to spawn a parallel computation. + * + * As an optimization, it internally checks whether the execution context is the + * standard implementation based on fork/join pools, and if it is, creates a + * `ForkJoinTaskSupport` that shares the same pool to forward its request to it. + * + * Otherwise, it uses an execution context exclusive `Tasks` implementation to + * divide the tasks into smaller chunks and execute operations on it. + */ +trait ExecutionContextTasks extends Tasks { def executionContext = environment val environment: ExecutionContext - // this part is a hack which allows switching - val driver: Tasks = executionContext match { + /** A driver serves as a target for this proxy `Tasks` object. + * + * If the execution context has the standard implementation and uses fork/join pools, + * the driver is `ForkJoinTaskSupport` with the same pool, as an optimization. + * Otherwise, the driver will be a Scala `Future`-based implementation. + */ + private val driver: Tasks = executionContext match { case eci: scala.concurrent.impl.ExecutionContextImpl => eci.executor match { case fjp: ForkJoinPool => new ForkJoinTaskSupport(fjp) - case tpe: ThreadPoolExecutor => new ThreadPoolTaskSupport(tpe) - case _ => ??? + case _ => new FutureTasks(environment) } - case _ => ??? + case _ => new FutureTasks(environment) } def execute[R, Tp](task: Task[R, Tp]): () => R = driver execute task @@ -554,16 +558,4 @@ trait ExecutionContextTasks extends Tasks { def executeAndWaitResult[R, Tp](task: Task[R, Tp]): R = driver executeAndWaitResult task def parallelismLevel = driver.parallelismLevel - } - - - - - - - - - - - diff --git a/src/library/scala/collection/parallel/immutable/ParHashMap.scala b/src/library/scala/collection/parallel/immutable/ParHashMap.scala index b25230bbeb..06455ba006 100644 --- a/src/library/scala/collection/parallel/immutable/ParHashMap.scala +++ b/src/library/scala/collection/parallel/immutable/ParHashMap.scala @@ -6,9 +6,8 @@ ** |/ ** \* */ -package scala.collection.parallel.immutable - - +package scala +package collection.parallel.immutable import scala.collection.parallel.ParMapLike import scala.collection.parallel.Combiner @@ -23,8 +22,6 @@ import scala.collection.immutable.{ HashMap, TrieIterator } import scala.annotation.unchecked.uncheckedVariance import scala.collection.parallel.Task - - /** Immutable parallel hash map, based on hash tries. * * $paralleliterableinfo @@ -109,7 +106,7 @@ self => } def next(): (K, V) = { i += 1 - val r = triter.next + val r = triter.next() r } def hasNext: Boolean = { @@ -135,10 +132,8 @@ self => println("other kind of node") } } - } - /** $factoryInfo * @define Coll `immutable.ParHashMap` * @define coll immutable parallel hash map @@ -157,7 +152,6 @@ object ParHashMap extends ParMapFactory[ParHashMap] { var totalcombines = new java.util.concurrent.atomic.AtomicInteger(0) } - private[parallel] abstract class HashMapCombiner[K, V] extends scala.collection.parallel.BucketCombiner[(K, V), ParHashMap[K, V], (K, V), HashMapCombiner[K, V]](HashMapCombiner.rootsize) { //self: EnvironmentPassingCombiner[(K, V), ParHashMap[K, V]] => @@ -330,30 +324,11 @@ extends scala.collection.parallel.BucketCombiner[(K, V), ParHashMap[K, V], (K, V } def shouldSplitFurther = howmany > scala.collection.parallel.thresholdFromSize(root.length, combinerTaskSupport.parallelismLevel) } - } - private[parallel] object HashMapCombiner { def apply[K, V] = new HashMapCombiner[K, V] {} // was: with EnvironmentPassingCombiner[(K, V), ParHashMap[K, V]] private[immutable] val rootbits = 5 private[immutable] val rootsize = 1 << 5 } - - - - - - - - - - - - - - - - - diff --git a/src/library/scala/collection/parallel/immutable/ParHashSet.scala b/src/library/scala/collection/parallel/immutable/ParHashSet.scala index e7e64eb2ad..65a632470e 100644 --- a/src/library/scala/collection/parallel/immutable/ParHashSet.scala +++ b/src/library/scala/collection/parallel/immutable/ParHashSet.scala @@ -6,7 +6,8 @@ ** |/ ** \* */ -package scala.collection.parallel.immutable +package scala +package collection.parallel.immutable @@ -106,7 +107,7 @@ self => } def next(): T = { i += 1 - triter.next + triter.next() } def hasNext: Boolean = { i < sz diff --git a/src/library/scala/collection/parallel/immutable/ParIterable.scala b/src/library/scala/collection/parallel/immutable/ParIterable.scala index 142f07ff26..417622facc 100644 --- a/src/library/scala/collection/parallel/immutable/ParIterable.scala +++ b/src/library/scala/collection/parallel/immutable/ParIterable.scala @@ -6,17 +6,13 @@ ** |/ ** \* */ - -package scala.collection +package scala +package collection package parallel.immutable - import scala.collection.generic._ - import scala.collection.parallel.ParIterableLike import scala.collection.parallel.Combiner -import scala.collection.GenIterable - /** A template trait for immutable parallel iterable collections. * @@ -30,22 +26,18 @@ import scala.collection.GenIterable * @since 2.9 */ trait ParIterable[+T] -extends scala.collection/*.immutable*/.GenIterable[T] +extends scala.collection.GenIterable[T] with scala.collection.parallel.ParIterable[T] with GenericParTemplate[T, ParIterable] with ParIterableLike[T, ParIterable[T], scala.collection.immutable.Iterable[T]] with Immutable { override def companion: GenericCompanion[ParIterable] with GenericParCompanion[ParIterable] = ParIterable - // if `immutable.ParIterableLike` is introduced, please move these 4 methods there override def toIterable: ParIterable[T] = this - override def toSeq: ParSeq[T] = toParCollection[T, ParSeq[T]](() => ParSeq.newCombiner[T]) - } - /** $factoryInfo */ object ParIterable extends ParFactory[ParIterable] { @@ -53,21 +45,5 @@ object ParIterable extends ParFactory[ParIterable] { new GenericCanCombineFrom[T] def newBuilder[T]: Combiner[T, ParIterable[T]] = ParVector.newBuilder[T] - def newCombiner[T]: Combiner[T, ParIterable[T]] = ParVector.newCombiner[T] - } - - - - - - - - - - - - - - diff --git a/src/library/scala/collection/parallel/immutable/ParMap.scala b/src/library/scala/collection/parallel/immutable/ParMap.scala index e904a7616b..2956c2a883 100644 --- a/src/library/scala/collection/parallel/immutable/ParMap.scala +++ b/src/library/scala/collection/parallel/immutable/ParMap.scala @@ -6,7 +6,8 @@ ** |/ ** \* */ -package scala.collection +package scala +package collection package parallel.immutable import scala.collection.generic.ParMapFactory @@ -62,7 +63,7 @@ self => * * Invoking transformer methods (e.g. `map`) will not preserve the default value. * - * @param d the function mapping keys to values, used for non-present keys + * @param d default value used for non-present keys * @return a wrapper of the map with a default value */ def withDefaultValue[U >: V](d: U): scala.collection.parallel.immutable.ParMap[K, U] = new ParMap.WithDefault[K, U](this, x => d) diff --git a/src/library/scala/collection/parallel/immutable/ParNumericRange.scala.disabled b/src/library/scala/collection/parallel/immutable/ParNumericRange.scala.disabled deleted file mode 100644 index 5f9c9c3d3d..0000000000 --- a/src/library/scala/collection/parallel/immutable/ParNumericRange.scala.disabled +++ /dev/null @@ -1,128 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - -package scala.collection.parallel.immutable - - - -import scala.collection.immutable.NumericRange -import scala.collection.parallel.Combiner -import scala.collection.generic.CanCombineFrom -import scala.collection.parallel.ParIterableIterator - - - -/** Parallel ranges for numeric types. - * - * $paralleliterableinfo - * - * $sideeffects - * - * @param range the sequential range this parallel range was obtained from - * - * @author Aleksandar Prokopec - * @since 2.9 - * - * @define Coll `immutable.ParRange` - * @define coll immutable parallel range - */ -@SerialVersionUID(1L) -class ParNumericRange[T](val range: NumericRange[T])(implicit num: Integral[T]) -extends ParSeq[T] - with Serializable -{ -self => - - def seq = range - - @inline final def length = range.length - - @inline final def apply(idx: Int) = range.apply(idx); - - def parallelIterator = new ParNumericRangeIterator with SCPI - - type SCPI = SignalContextPassingIterator[ParNumericRangeIterator] - - class ParNumericRangeIterator(range: NumericRange[T] = self.range, num: Integral[T] = self.num) - extends ParIterator { - me: SignalContextPassingIterator[ParNumericRangeIterator] => - override def toString = "ParNumericRangeIterator(over: " + range + ")" - private var ind = 0 - private val len = range.length - - final def remaining = len - ind - - final def hasNext = ind < len - - final def next = if (hasNext) { - val r = range.apply(ind) - ind += 1 - r - } else Iterator.empty.next - - private def rangeleft: NumericRange[T] = range.drop(ind) - - def dup = new ParNumericRangeIterator(rangeleft) with SCPI - - def split = { - val rleft = rangeleft - val elemleft = rleft.length - if (elemleft < 2) Seq(new ParNumericRangeIterator(rleft) with SCPI) - else Seq( - new ParNumericRangeIterator(rleft.take(elemleft / 2)) with SCPI, - new ParNumericRangeIterator(rleft.drop(elemleft / 2)) with SCPI - ) - } - - def psplit(sizes: Int*) = { - var rleft = rangeleft - for (sz <- sizes) yield { - val fronttaken = rleft.take(sz) - rleft = rleft.drop(sz) - new ParNumericRangeIterator(fronttaken) with SCPI - } - } - - /* accessors */ - - override def foreach[U](f: T => U): Unit = { - rangeleft.foreach(f) - ind = len - } - - override def reduce[U >: T](op: (U, U) => U): U = { - val r = rangeleft.reduceLeft(op) - ind = len - r - } - - /* transformers */ - - override def map2combiner[S, That](f: T => S, cb: Combiner[S, That]): Combiner[S, That] = { - while (hasNext) { - cb += f(next) - } - cb - } - } - -} - - -object ParNumericRange { - def apply[T](start: T, end: T, step: T, inclusive: Boolean)(implicit num: Integral[T]) = new ParNumericRange[T]( - if (inclusive) NumericRange.inclusive(start, end, step)(num) - else NumericRange.apply(start, end, step)(num) - ) -} - - - - - diff --git a/src/library/scala/collection/parallel/immutable/ParRange.scala b/src/library/scala/collection/parallel/immutable/ParRange.scala index 0c9f82ba2a..ec90de3a7d 100644 --- a/src/library/scala/collection/parallel/immutable/ParRange.scala +++ b/src/library/scala/collection/parallel/immutable/ParRange.scala @@ -6,13 +6,13 @@ ** |/ ** \* */ -package scala.collection.parallel.immutable +package scala +package collection.parallel.immutable import scala.collection.immutable.Range import scala.collection.parallel.Combiner import scala.collection.parallel.SeqSplitter import scala.collection.generic.CanCombineFrom -import scala.collection.parallel.IterableSplitter import scala.collection.Iterator /** Parallel ranges. @@ -42,7 +42,7 @@ self => @inline final def length = range.length - @inline final def apply(idx: Int) = range.apply(idx); + @inline final def apply(idx: Int) = range.apply(idx) def splitter = new ParRangeIterator @@ -60,7 +60,7 @@ self => val r = range.apply(ind) ind += 1 r - } else Iterator.empty.next + } else Iterator.empty.next() private def rangeleft = range.drop(ind) @@ -107,7 +107,7 @@ self => cb } } - + } object ParRange { diff --git a/src/library/scala/collection/parallel/immutable/ParSeq.scala b/src/library/scala/collection/parallel/immutable/ParSeq.scala index aa19307387..f0502fbbcb 100644 --- a/src/library/scala/collection/parallel/immutable/ParSeq.scala +++ b/src/library/scala/collection/parallel/immutable/ParSeq.scala @@ -6,11 +6,10 @@ ** |/ ** \* */ - -package scala.collection +package scala +package collection package parallel.immutable - import scala.collection.generic.GenericParTemplate import scala.collection.generic.GenericCompanion import scala.collection.generic.GenericParCompanion @@ -18,9 +17,6 @@ import scala.collection.generic.CanCombineFrom import scala.collection.generic.ParFactory import scala.collection.parallel.ParSeqLike import scala.collection.parallel.Combiner -import scala.collection.GenSeq - - /** An immutable variant of `ParSeq`. * @@ -38,7 +34,6 @@ extends scala.collection/*.immutable*/.GenSeq[T] override def toSeq: ParSeq[T] = this } - /** $factoryInfo * @define Coll `mutable.ParSeq` * @define coll mutable parallel sequence @@ -47,9 +42,5 @@ object ParSeq extends ParFactory[ParSeq] { implicit def canBuildFrom[T]: CanCombineFrom[Coll, T, ParSeq[T]] = new GenericCanCombineFrom[T] def newBuilder[T]: Combiner[T, ParSeq[T]] = ParVector.newBuilder[T] - def newCombiner[T]: Combiner[T, ParSeq[T]] = ParVector.newCombiner[T] } - - - diff --git a/src/library/scala/collection/parallel/immutable/ParSet.scala b/src/library/scala/collection/parallel/immutable/ParSet.scala index 3622377a55..7837d6f264 100644 --- a/src/library/scala/collection/parallel/immutable/ParSet.scala +++ b/src/library/scala/collection/parallel/immutable/ParSet.scala @@ -6,10 +6,10 @@ ** |/ ** \* */ -package scala.collection +package scala +package collection package parallel.immutable -import scala.collection.GenSet import scala.collection.generic._ import scala.collection.parallel.ParSetLike import scala.collection.parallel.Combiner diff --git a/src/library/scala/collection/parallel/immutable/ParVector.scala b/src/library/scala/collection/parallel/immutable/ParVector.scala index 1ee7f4ae69..c2c1d042e1 100644 --- a/src/library/scala/collection/parallel/immutable/ParVector.scala +++ b/src/library/scala/collection/parallel/immutable/ParVector.scala @@ -6,13 +6,10 @@ ** |/ ** \* */ - -package scala.collection +package scala +package collection package parallel.immutable - - - import scala.collection.generic.{GenericParTemplate, CanCombineFrom, ParFactory} import scala.collection.parallel.ParSeqLike import scala.collection.parallel.Combiner @@ -22,8 +19,6 @@ import immutable.Vector import immutable.VectorBuilder import immutable.VectorIterator - - /** Immutable parallel vectors, based on vectors. * * $paralleliterableinfo @@ -82,11 +77,8 @@ extends ParSeq[T] splitted.map(v => new ParVector(v).splitter.asInstanceOf[ParVectorIterator]) } } - } - - /** $factoryInfo * @define Coll `immutable.ParVector` * @define coll immutable parallel vector @@ -100,8 +92,6 @@ object ParVector extends ParFactory[ParVector] { def newCombiner[T]: Combiner[T, ParVector[T]] = new LazyParVectorCombiner[T] // was: with EPC[T, ParVector[T]] } - - private[immutable] class LazyParVectorCombiner[T] extends Combiner[T, ParVector[T]] { //self: EnvironmentPassingCombiner[T, ParVector[T]] => var sz = 0 @@ -135,11 +125,4 @@ private[immutable] class LazyParVectorCombiner[T] extends Combiner[T, ParVector[ vectors ++= that.vectors this } - } - - - - - - diff --git a/src/library/scala/collection/parallel/immutable/package.scala b/src/library/scala/collection/parallel/immutable/package.scala index 5ca0724ffc..8fd84eaf4d 100644 --- a/src/library/scala/collection/parallel/immutable/package.scala +++ b/src/library/scala/collection/parallel/immutable/package.scala @@ -6,7 +6,8 @@ ** |/ ** \* */ -package scala.collection.parallel +package scala +package collection.parallel package immutable { /** A (parallel) sequence consisting of `length` elements `elem`. Used in the `padTo` method. diff --git a/src/library/scala/collection/parallel/mutable/LazyCombiner.scala b/src/library/scala/collection/parallel/mutable/LazyCombiner.scala index 12b2bc5008..5ab2bb81c6 100644 --- a/src/library/scala/collection/parallel/mutable/LazyCombiner.scala +++ b/src/library/scala/collection/parallel/mutable/LazyCombiner.scala @@ -6,7 +6,8 @@ ** |/ ** \* */ -package scala.collection.parallel.mutable +package scala +package collection.parallel.mutable import scala.collection.generic.Growable import scala.collection.generic.Sizing @@ -29,6 +30,7 @@ trait LazyCombiner[Elem, +To, Buff <: Growable[Elem] with Sizing] extends Combin def result: To = allocateAndCopy def clear() = { chain.clear() } def combine[N <: Elem, NewTo >: To](other: Combiner[N, NewTo]): Combiner[N, NewTo] = if (this ne other) { + import language.existentials // FIXME: See SI-7750 if (other.isInstanceOf[LazyCombiner[_, _, _]]) { val that = other.asInstanceOf[LazyCombiner[Elem, To, Buff]] newLazyCombiner(chain ++= that.chain) diff --git a/src/library/scala/collection/parallel/mutable/ParArray.scala b/src/library/scala/collection/parallel/mutable/ParArray.scala index 0a4f30131f..d0d022db4b 100644 --- a/src/library/scala/collection/parallel/mutable/ParArray.scala +++ b/src/library/scala/collection/parallel/mutable/ParArray.scala @@ -29,8 +29,6 @@ import scala.collection.mutable.Builder import scala.collection.GenTraversableOnce import scala.reflect.ClassTag - - /** Parallel sequence holding elements in a linear array. * * `ParArray` is a parallel sequence with a predefined size. The size of the array @@ -181,10 +179,10 @@ self => override def fold[U >: T](z: U)(op: (U, U) => U): U = foldLeft[U](z)(op) - override def aggregate[S](z: S)(seqop: (S, T) => S, combop: (S, S) => S): S = foldLeft[S](z)(seqop) + override def aggregate[S](z: =>S)(seqop: (S, T) => S, combop: (S, S) => S): S = foldLeft[S](z)(seqop) override def sum[U >: T](implicit num: Numeric[U]): U = { - var s = sum_quick(num, arr, until, i, num.zero) + val s = sum_quick(num, arr, until, i, num.zero) i = until s } @@ -200,7 +198,7 @@ self => } override def product[U >: T](implicit num: Numeric[U]): U = { - var p = product_quick(num, arr, until, i, num.one) + val p = product_quick(num, arr, until, i, num.one) i = until p } @@ -226,7 +224,7 @@ self => if (all) i = nextuntil else { i = until - abort + abort() } if (isAborted) return false @@ -241,7 +239,7 @@ self => if (p(a(j).asInstanceOf[T])) j += 1 else return false } - return true + true } override def exists(p: T => Boolean): Boolean = { @@ -254,7 +252,7 @@ self => some = exists_quick(p, array, nextuntil, i) if (some) { i = until - abort + abort() } else i = nextuntil if (isAborted) return true @@ -269,7 +267,7 @@ self => if (p(a(j).asInstanceOf[T])) return true else j += 1 } - return false + false } override def find(p: T => Boolean): Option[T] = { @@ -283,7 +281,7 @@ self => if (r != None) { i = until - abort + abort() } else i = nextuntil if (isAborted) return r @@ -298,7 +296,7 @@ self => if (p(elem)) return Some(elem) else j += 1 } - return None + None } override def drop(n: Int): ParArrayIterator = { @@ -405,9 +403,10 @@ self => private def collect2combiner_quick[S, That](pf: PartialFunction[T, S], a: Array[Any], cb: Builder[S, That], ntil: Int, from: Int) { var j = from + val runWith = pf.runWith(b => cb += b) while (j < ntil) { val curr = a(j).asInstanceOf[T] - if (pf.isDefinedAt(curr)) cb += pf(curr) + runWith(curr) j += 1 } } @@ -432,7 +431,7 @@ self => private def filter2combiner_quick[U >: T, This](pred: T => Boolean, cb: Builder[U, This], a: Array[Any], ntil: Int, from: Int) { var j = i while(j < ntil) { - var curr = a(j).asInstanceOf[T] + val curr = a(j).asInstanceOf[T] if (pred(curr)) cb += curr j += 1 } @@ -447,7 +446,7 @@ self => private def filterNot2combiner_quick[U >: T, This](pred: T => Boolean, cb: Builder[U, This], a: Array[Any], ntil: Int, from: Int) { var j = i while(j < ntil) { - var curr = a(j).asInstanceOf[T] + val curr = a(j).asInstanceOf[T] if (!pred(curr)) cb += curr j += 1 } @@ -576,8 +575,6 @@ self => /* operations */ - private def asTask[R, Tp](t: Any) = t.asInstanceOf[Task[R, Tp]] - private def buildsArray[S, That](c: Builder[S, That]) = c.isInstanceOf[ParArrayCombiner[_]] override def map[S, That](f: T => S)(implicit bf: CanBuildFrom[ParArray[T], S, That]) = if (buildsArray(bf(repr))) { @@ -612,7 +609,8 @@ self => class ScanToArray[U >: T](tree: ScanTree[U], z: U, op: (U, U) => U, targetarr: Array[Any]) extends Task[Unit, ScanToArray[U]] { - var result = (); + var result = () + def leaf(prev: Option[Unit]) = iterate(tree) private def iterate(tree: ScanTree[U]): Unit = tree match { case ScanNode(left, right) => @@ -648,7 +646,8 @@ self => } class Map[S](f: T => S, targetarr: Array[Any], offset: Int, howmany: Int) extends Task[Unit, Map[S]] { - var result = (); + var result = () + def leaf(prev: Option[Unit]) = { val tarr = targetarr val sarr = array @@ -701,7 +700,7 @@ object ParArray extends ParFactory[ParArray] { private def wrapOrRebuild[T](arr: AnyRef, sz: Int) = arr match { case arr: Array[AnyRef] => new ParArray[T](new ExposedArraySeq[T](arr, sz)) - case _ => new ParArray[T](new ExposedArraySeq[T](runtime.ScalaRunTime.toObjectArray(arr), sz)) + case _ => new ParArray[T](new ExposedArraySeq[T](scala.runtime.ScalaRunTime.toObjectArray(arr), sz)) } def createFromCopy[T <: AnyRef : ClassTag](arr: Array[T]): ParArray[T] = { @@ -719,27 +718,3 @@ object ParArray extends ParFactory[ParArray] { } } - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/library/scala/collection/parallel/mutable/ParFlatHashTable.scala b/src/library/scala/collection/parallel/mutable/ParFlatHashTable.scala index 8bc108a738..62165ae0d2 100644 --- a/src/library/scala/collection/parallel/mutable/ParFlatHashTable.scala +++ b/src/library/scala/collection/parallel/mutable/ParFlatHashTable.scala @@ -6,7 +6,8 @@ ** |/ ** \* */ -package scala.collection +package scala +package collection package parallel.mutable import scala.collection.parallel.IterableSplitter @@ -27,32 +28,28 @@ trait ParFlatHashTable[T] extends scala.collection.mutable.FlatHashTable[T] { extends IterableSplitter[T] with SizeMapUtils { import scala.collection.DebugUtils._ - private var traversed = 0 - private val itertable = table + private[this] var traversed = 0 + private[this] val itertable = table if (hasNext) scan() - private def scan() { + private[this] def scan() { while (itertable(idx) eq null) { idx += 1 } } - private def checkbounds() = if (idx >= itertable.length) { - throw new IndexOutOfBoundsException(idx.toString) - } - def newIterator(index: Int, until: Int, totalsize: Int): IterableSplitter[T] def remaining = totalsize - traversed def hasNext = traversed < totalsize def next() = if (hasNext) { - val r = itertable(idx).asInstanceOf[T] + val r = entryToElem(itertable(idx)) traversed += 1 idx += 1 if (hasNext) scan() r - } else Iterator.empty.next + } else Iterator.empty.next() def dup = newIterator(idx, until, totalsize) def split = if (remaining > 1) { val divpt = (until + idx) / 2 @@ -102,11 +99,5 @@ trait ParFlatHashTable[T] extends scala.collection.mutable.FlatHashTable[T] { } count } - - private def check() = if (table.slice(idx, until).count(_ != null) != remaining) { - println("Invariant broken: " + debugInformation) - assert(false) - } } - } diff --git a/src/library/scala/collection/parallel/mutable/ParHashMap.scala b/src/library/scala/collection/parallel/mutable/ParHashMap.scala index 11588e555b..bb3737f18e 100644 --- a/src/library/scala/collection/parallel/mutable/ParHashMap.scala +++ b/src/library/scala/collection/parallel/mutable/ParHashMap.scala @@ -6,12 +6,10 @@ ** |/ ** \* */ - -package scala.collection.parallel +package scala +package collection.parallel package mutable - - import scala.collection.generic._ import scala.collection.mutable.DefaultEntry import scala.collection.mutable.HashEntry @@ -19,8 +17,6 @@ import scala.collection.mutable.HashTable import scala.collection.mutable.UnrolledBuffer import scala.collection.parallel.Task - - /** A parallel hash map. * * `ParHashMap` is a parallel map which internally keeps elements within a hash table. @@ -97,7 +93,8 @@ self => class ParHashMapIterator(start: Int, untilIdx: Int, totalSize: Int, e: DefaultEntry[K, V]) extends EntryIterator[(K, V), ParHashMapIterator](start, untilIdx, totalSize, e) { - def entry2item(entry: DefaultEntry[K, V]) = (entry.key, entry.value); + def entry2item(entry: DefaultEntry[K, V]) = (entry.key, entry.value) + def newIterator(idxFrom: Int, idxUntil: Int, totalSz: Int, es: DefaultEntry[K, V]) = new ParHashMapIterator(idxFrom, idxUntil, totalSz, es) } @@ -143,10 +140,8 @@ self => else ("Element " + e.key + " at " + i + " with " + elemHashCode(e.key) + " maps to " + index(elemHashCode(e.key))) :: check(e.next) check(table(i)) } - } - /** $factoryInfo * @define Coll `mutable.ParHashMap` * @define coll parallel hash map @@ -161,14 +156,12 @@ object ParHashMap extends ParMapFactory[ParHashMap] { implicit def canBuildFrom[K, V]: CanCombineFrom[Coll, (K, V), ParHashMap[K, V]] = new CanCombineFromMap[K, V] } - private[mutable] abstract class ParHashMapCombiner[K, V](private val tableLoadFactor: Int) extends scala.collection.parallel.BucketCombiner[(K, V), ParHashMap[K, V], DefaultEntry[K, V], ParHashMapCombiner[K, V]](ParHashMapCombiner.numblocks) with scala.collection.mutable.HashTable.HashUtils[K] { - private var mask = ParHashMapCombiner.discriminantmask - private var nonmasklen = ParHashMapCombiner.nonmasklength - private var seedvalue = 27 + private val nonmasklen = ParHashMapCombiner.nonmasklength + private val seedvalue = 27 def +=(elem: (K, V)) = { sz += 1 @@ -232,8 +225,7 @@ extends scala.collection.parallel.BucketCombiner[(K, V), ParHashMap[K, V], Defau def setSize(sz: Int) = tableSize = sz def insertEntry(/*block: Int, */e: DefaultEntry[K, V]) = { var h = index(elemHashCode(e.key)) - // assertCorrectBlock(h, block) - var olde = table(h).asInstanceOf[DefaultEntry[K, V]] + val olde = table(h).asInstanceOf[DefaultEntry[K, V]] // check if key already exists var ce = olde @@ -252,13 +244,6 @@ extends scala.collection.parallel.BucketCombiner[(K, V), ParHashMap[K, V], Defau true } else false } - private def assertCorrectBlock(h: Int, block: Int) { - val blocksize = table.length / (1 << ParHashMapCombiner.discriminantbits) - if (!(h >= block * blocksize && h < (block + 1) * blocksize)) { - println("trying to put " + h + " into block no.: " + block + ", range: [" + block * blocksize + ", " + (block + 1) * blocksize + ">") - assert(h >= block * blocksize && h < (block + 1) * blocksize) - } - } protected def createNewEntry[X](key: K, x: X) = ??? } @@ -288,7 +273,6 @@ extends scala.collection.parallel.BucketCombiner[(K, V), ParHashMap[K, V], Defau val chunksz = unrolled.size while (i < chunksz) { val elem = chunkarr(i) - // assertCorrectBlock(block, elem.key) if (t.insertEntry(elem)) insertcount += 1 i += 1 } @@ -297,13 +281,6 @@ extends scala.collection.parallel.BucketCombiner[(K, V), ParHashMap[K, V], Defau } insertcount } - private def assertCorrectBlock(block: Int, k: K) { - val hc = improve(elemHashCode(k), seedvalue) - if ((hc >>> nonmasklen) != block) { - println(hc + " goes to " + (hc >>> nonmasklen) + ", while expected block is " + block) - assert((hc >>> nonmasklen) == block) - } - } def split = { val fp = howmany / 2 List(new FillBlocks(buckets, table, offset, fp), new FillBlocks(buckets, table, offset + fp, howmany - fp)) @@ -313,29 +290,13 @@ extends scala.collection.parallel.BucketCombiner[(K, V), ParHashMap[K, V], Defau } def shouldSplitFurther = howmany > scala.collection.parallel.thresholdFromSize(ParHashMapCombiner.numblocks, combinerTaskSupport.parallelismLevel) } - } - private[parallel] object ParHashMapCombiner { private[mutable] val discriminantbits = 5 private[mutable] val numblocks = 1 << discriminantbits - private[mutable] val discriminantmask = ((1 << discriminantbits) - 1); + private[mutable] val discriminantmask = ((1 << discriminantbits) - 1) private[mutable] val nonmasklength = 32 - discriminantbits def apply[K, V] = new ParHashMapCombiner[K, V](HashTable.defaultLoadFactor) {} // was: with EnvironmentPassingCombiner[(K, V), ParHashMap[K, V]] } - - - - - - - - - - - - - - diff --git a/src/library/scala/collection/parallel/mutable/ParHashSet.scala b/src/library/scala/collection/parallel/mutable/ParHashSet.scala index 57fab57348..1e3d57e0e5 100644 --- a/src/library/scala/collection/parallel/mutable/ParHashSet.scala +++ b/src/library/scala/collection/parallel/mutable/ParHashSet.scala @@ -6,7 +6,8 @@ ** |/ ** \* */ -package scala.collection.parallel.mutable +package scala +package collection.parallel.mutable @@ -60,18 +61,18 @@ extends ParSet[T] override def seq = new scala.collection.mutable.HashSet(hashTableContents) def +=(elem: T) = { - addEntry(elem) + addElem(elem) this } def -=(elem: T) = { - removeEntry(elem) + removeElem(elem) this } override def stringPrefix = "ParHashSet" - def contains(elem: T) = containsEntry(elem) + def contains(elem: T) = containsElem(elem) def splitter = new ParHashSetIterator(0, table.length, size) @@ -117,23 +118,23 @@ object ParHashSet extends ParSetFactory[ParHashSet] { private[mutable] abstract class ParHashSetCombiner[T](private val tableLoadFactor: Int) -extends scala.collection.parallel.BucketCombiner[T, ParHashSet[T], Any, ParHashSetCombiner[T]](ParHashSetCombiner.numblocks) +extends scala.collection.parallel.BucketCombiner[T, ParHashSet[T], AnyRef, ParHashSetCombiner[T]](ParHashSetCombiner.numblocks) with scala.collection.mutable.FlatHashTable.HashUtils[T] { //self: EnvironmentPassingCombiner[T, ParHashSet[T]] => - private var mask = ParHashSetCombiner.discriminantmask - private var nonmasklen = ParHashSetCombiner.nonmasklength - private var seedvalue = 27 + private val nonmasklen = ParHashSetCombiner.nonmasklength + private val seedvalue = 27 def +=(elem: T) = { + val entry = elemToEntry(elem) sz += 1 - val hc = improve(elemHashCode(elem), seedvalue) + val hc = improve(entry.hashCode, seedvalue) val pos = hc >>> nonmasklen if (buckets(pos) eq null) { // initialize bucket - buckets(pos) = new UnrolledBuffer[Any] + buckets(pos) = new UnrolledBuffer[AnyRef] } // add to bucket - buckets(pos) += elem + buckets(pos) += entry this } @@ -147,7 +148,7 @@ with scala.collection.mutable.FlatHashTable.HashUtils[T] { val table = new AddingFlatHashTable(size, tableLoadFactor, seedvalue) val (inserted, leftovers) = combinerTaskSupport.executeAndWaitResult(new FillBlocks(buckets, table, 0, buckets.length)) var leftinserts = 0 - for (elem <- leftovers) leftinserts += table.insertEntry(0, table.tableLength, elem.asInstanceOf[T]) + for (entry <- leftovers) leftinserts += table.insertEntry(0, table.tableLength, entry) table.setSize(leftinserts + inserted) table.hashTableContents } @@ -159,10 +160,10 @@ with scala.collection.mutable.FlatHashTable.HashUtils[T] { sizeMapInit(table.length) seedvalue = ParHashSetCombiner.this.seedvalue for { - buffer <- buckets; - if buffer ne null; - elem <- buffer - } addEntry(elem.asInstanceOf[T]) + buffer <- buckets + if buffer ne null + entry <- buffer + } addEntry(entry) } tbl.hashTableContents } @@ -189,12 +190,12 @@ with scala.collection.mutable.FlatHashTable.HashUtils[T] { def setSize(sz: Int) = tableSize = sz /** - * The elements are added using the `insertEntry` method. This method accepts three + * The elements are added using the `insertElem` method. This method accepts three * arguments: * * @param insertAt where to add the element (set to -1 to use its hashcode) * @param comesBefore the position before which the element should be added to - * @param elem the element to be added + * @param newEntry the element to be added * * If the element is to be inserted at the position corresponding to its hash code, * the table will try to add the element in such a position if possible. Collisions are resolved @@ -206,17 +207,17 @@ with scala.collection.mutable.FlatHashTable.HashUtils[T] { * If the element is already present in the hash table, it is not added, and this method * returns 0. If the element is added, it returns 1. */ - def insertEntry(insertAt: Int, comesBefore: Int, elem: T): Int = { + def insertEntry(insertAt: Int, comesBefore: Int, newEntry : AnyRef): Int = { var h = insertAt - if (h == -1) h = index(elemHashCode(elem)) - var entry = table(h) - while (null != entry) { - if (entry == elem) return 0 + if (h == -1) h = index(newEntry.hashCode) + var curEntry = table(h) + while (null != curEntry) { + if (curEntry == newEntry) return 0 h = h + 1 // we *do not* do `(h + 1) % table.length` here, because we'll never overflow!! if (h >= comesBefore) return -1 - entry = table(h) + curEntry = table(h) } - table(h) = elem.asInstanceOf[AnyRef] + table(h) = newEntry // this is incorrect since we set size afterwards anyway and a counter // like this would not even work: @@ -233,13 +234,14 @@ with scala.collection.mutable.FlatHashTable.HashUtils[T] { /* tasks */ - class FillBlocks(buckets: Array[UnrolledBuffer[Any]], table: AddingFlatHashTable, val offset: Int, val howmany: Int) - extends Task[(Int, UnrolledBuffer[Any]), FillBlocks] { - var result = (Int.MinValue, new UnrolledBuffer[Any]); - def leaf(prev: Option[(Int, UnrolledBuffer[Any])]) { + class FillBlocks(buckets: Array[UnrolledBuffer[AnyRef]], table: AddingFlatHashTable, val offset: Int, val howmany: Int) + extends Task[(Int, UnrolledBuffer[AnyRef]), FillBlocks] { + var result = (Int.MinValue, new UnrolledBuffer[AnyRef]) + + def leaf(prev: Option[(Int, UnrolledBuffer[AnyRef])]) { var i = offset var totalinserts = 0 - var leftover = new UnrolledBuffer[Any]() + var leftover = new UnrolledBuffer[AnyRef]() while (i < (offset + howmany)) { val (inserted, intonextblock) = fillBlock(i, buckets(i), leftover) totalinserts += inserted @@ -251,11 +253,11 @@ with scala.collection.mutable.FlatHashTable.HashUtils[T] { private val blocksize = table.tableLength >> ParHashSetCombiner.discriminantbits private def blockStart(block: Int) = block * blocksize private def nextBlockStart(block: Int) = (block + 1) * blocksize - private def fillBlock(block: Int, elems: UnrolledBuffer[Any], leftovers: UnrolledBuffer[Any]): (Int, UnrolledBuffer[Any]) = { + private def fillBlock(block: Int, elems: UnrolledBuffer[AnyRef], leftovers: UnrolledBuffer[AnyRef]): (Int, UnrolledBuffer[AnyRef]) = { val beforePos = nextBlockStart(block) // store the elems - val (elemsIn, elemsLeft) = if (elems != null) insertAll(-1, beforePos, elems) else (0, UnrolledBuffer[Any]()) + val (elemsIn, elemsLeft) = if (elems != null) insertAll(-1, beforePos, elems) else (0, UnrolledBuffer[AnyRef]()) // store the leftovers val (leftoversIn, leftoversLeft) = insertAll(blockStart(block), beforePos, leftovers) @@ -263,21 +265,21 @@ with scala.collection.mutable.FlatHashTable.HashUtils[T] { // return the no. of stored elements tupled with leftovers (elemsIn + leftoversIn, elemsLeft concat leftoversLeft) } - private def insertAll(atPos: Int, beforePos: Int, elems: UnrolledBuffer[Any]): (Int, UnrolledBuffer[Any]) = { - var leftovers = new UnrolledBuffer[Any] + private def insertAll(atPos: Int, beforePos: Int, elems: UnrolledBuffer[AnyRef]): (Int, UnrolledBuffer[AnyRef]) = { + val leftovers = new UnrolledBuffer[AnyRef] var inserted = 0 var unrolled = elems.headPtr var i = 0 - var t = table + val t = table while (unrolled ne null) { val chunkarr = unrolled.array val chunksz = unrolled.size while (i < chunksz) { - val elem = chunkarr(i) - val res = t.insertEntry(atPos, beforePos, elem.asInstanceOf[T]) + val entry = chunkarr(i) + val res = t.insertEntry(atPos, beforePos, entry) if (res >= 0) inserted += res - else leftovers += elem + else leftovers += entry i += 1 } i = 0 @@ -319,7 +321,7 @@ with scala.collection.mutable.FlatHashTable.HashUtils[T] { private[parallel] object ParHashSetCombiner { private[mutable] val discriminantbits = 5 private[mutable] val numblocks = 1 << discriminantbits - private[mutable] val discriminantmask = ((1 << discriminantbits) - 1); + private[mutable] val discriminantmask = ((1 << discriminantbits) - 1) private[mutable] val nonmasklength = 32 - discriminantbits def apply[T] = new ParHashSetCombiner[T](FlatHashTable.defaultLoadFactor) {} //with EnvironmentPassingCombiner[T, ParHashSet[T]] diff --git a/src/library/scala/collection/parallel/mutable/ParHashTable.scala b/src/library/scala/collection/parallel/mutable/ParHashTable.scala index 66ddef6a1e..423b891d48 100644 --- a/src/library/scala/collection/parallel/mutable/ParHashTable.scala +++ b/src/library/scala/collection/parallel/mutable/ParHashTable.scala @@ -6,18 +6,13 @@ ** |/ ** \* */ - -package scala.collection +package scala +package collection package parallel.mutable - - - import scala.collection.mutable.HashEntry import scala.collection.parallel.IterableSplitter - - /** Provides functionality for hash tables with linked list buckets, * enriching the data structure by fulfilling certain requirements * for their parallel construction and iteration. @@ -110,7 +105,7 @@ trait ParHashTable[K, Entry >: Null <: HashEntry[K, Entry]] extends scala.collec } else Seq(this.asInstanceOf[IterRepr]) private def convertToArrayBuffer(chainhead: Entry): mutable.ArrayBuffer[T] = { - var buff = mutable.ArrayBuffer[Entry]() + val buff = mutable.ArrayBuffer[Entry]() var curr = chainhead while (curr ne null) { buff += curr @@ -145,11 +140,4 @@ trait ParHashTable[K, Entry >: Null <: HashEntry[K, Entry]] extends scala.collec c } } - } - - - - - - diff --git a/src/library/scala/collection/parallel/mutable/ParIterable.scala b/src/library/scala/collection/parallel/mutable/ParIterable.scala index 7090c510a0..4659149106 100644 --- a/src/library/scala/collection/parallel/mutable/ParIterable.scala +++ b/src/library/scala/collection/parallel/mutable/ParIterable.scala @@ -6,14 +6,12 @@ ** |/ ** \* */ -package scala.collection.parallel.mutable - +package scala +package collection +package parallel.mutable import scala.collection.generic._ -import scala.collection.parallel.ParIterableLike -import scala.collection.parallel.Combiner -import scala.collection.GenIterable - +import scala.collection.parallel.{ ParIterableLike, Combiner } /** A template trait for mutable parallel iterable collections. * @@ -26,7 +24,7 @@ import scala.collection.GenIterable * @author Aleksandar Prokopec * @since 2.9 */ -trait ParIterable[T] extends scala.collection/*.mutable*/.GenIterable[T] +trait ParIterable[T] extends scala.collection.GenIterable[T] with scala.collection.parallel.ParIterable[T] with GenericParTemplate[T, ParIterable] with ParIterableLike[T, ParIterable[T], Iterable[T]] @@ -45,24 +43,8 @@ trait ParIterable[T] extends scala.collection/*.mutable*/.GenIterable[T] /** $factoryInfo */ object ParIterable extends ParFactory[ParIterable] { - implicit def canBuildFrom[T]: CanCombineFrom[Coll, T, ParIterable[T]] = - new GenericCanCombineFrom[T] + implicit def canBuildFrom[T]: CanCombineFrom[Coll, T, ParIterable[T]] = new GenericCanCombineFrom[T] def newBuilder[T]: Combiner[T, ParIterable[T]] = ParArrayCombiner[T] - def newCombiner[T]: Combiner[T, ParIterable[T]] = ParArrayCombiner[T] } - - - - - - - - - - - - - - diff --git a/src/library/scala/collection/parallel/mutable/ParMap.scala b/src/library/scala/collection/parallel/mutable/ParMap.scala index 2250a38466..8110f9dc0a 100644 --- a/src/library/scala/collection/parallel/mutable/ParMap.scala +++ b/src/library/scala/collection/parallel/mutable/ParMap.scala @@ -6,17 +6,13 @@ ** |/ ** \* */ - -package scala.collection.parallel.mutable - - - +package scala +package collection +package parallel.mutable import scala.collection.generic._ import scala.collection.parallel.Combiner - - /** A template trait for mutable parallel maps. * * $sideeffects @@ -28,11 +24,11 @@ import scala.collection.parallel.Combiner * @since 2.9 */ trait ParMap[K, V] -extends scala.collection/*.mutable*/.GenMap[K, V] - with scala.collection.parallel.ParMap[K, V] - with /* mutable */ ParIterable[(K, V)] +extends GenMap[K, V] + with parallel.ParMap[K, V] + with ParIterable[(K, V)] with GenericParMapTemplate[K, V, ParMap] - with /* mutable */ ParMapLike[K, V, ParMap[K, V], scala.collection.mutable.Map[K, V]] + with ParMapLike[K, V, ParMap[K, V], mutable.Map[K, V]] { protected[this] override def newCombiner: Combiner[(K, V), ParMap[K, V]] = ParMap.newCombiner[K, V] @@ -59,15 +55,12 @@ extends scala.collection/*.mutable*/.GenMap[K, V] * * Invoking transformer methods (e.g. `map`) will not preserve the default value. * - * @param d the function mapping keys to values, used for non-present keys + * @param d default value used for non-present keys * @return a wrapper of the map with a default value */ def withDefaultValue(d: V): scala.collection.parallel.mutable.ParMap[K, V] = new ParMap.WithDefault[K, V](this, x => d) - } - - object ParMap extends ParMapFactory[ParMap] { def empty[K, V]: ParMap[K, V] = new ParHashMap[K, V] @@ -94,22 +87,3 @@ object ParMap extends ParMapFactory[ParMap] { override def withDefaultValue(d: V): ParMap[K, V] = new WithDefault[K, V](underlying, x => d) } } - - - - - - - - - - - - - - - - - - - diff --git a/src/library/scala/collection/parallel/mutable/ParMapLike.scala b/src/library/scala/collection/parallel/mutable/ParMapLike.scala index cdcfc59f8f..42027f5bac 100644 --- a/src/library/scala/collection/parallel/mutable/ParMapLike.scala +++ b/src/library/scala/collection/parallel/mutable/ParMapLike.scala @@ -6,19 +6,15 @@ ** |/ ** \* */ -package scala.collection.parallel +package scala +package collection.parallel package mutable - - import scala.collection.generic._ -import scala.collection.mutable.Builder import scala.collection.mutable.Cloneable import scala.collection.generic.Growable import scala.collection.generic.Shrinkable - - /** A template trait for mutable parallel maps. This trait is to be mixed in * with concrete parallel maps to override the representation type. * @@ -53,6 +49,4 @@ extends scala.collection.GenMapLike[K, V, Repr] def -(key: K) = this.clone() -= key def clear(): Unit - } - diff --git a/src/library/scala/collection/parallel/mutable/ParSeq.scala b/src/library/scala/collection/parallel/mutable/ParSeq.scala index 95a4d4a13a..35be2669f8 100644 --- a/src/library/scala/collection/parallel/mutable/ParSeq.scala +++ b/src/library/scala/collection/parallel/mutable/ParSeq.scala @@ -6,9 +6,8 @@ ** |/ ** \* */ - -package scala.collection.parallel.mutable - +package scala +package collection.parallel.mutable import scala.collection.generic.GenericParTemplate import scala.collection.generic.GenericCompanion @@ -17,12 +16,6 @@ import scala.collection.generic.CanCombineFrom import scala.collection.generic.ParFactory import scala.collection.parallel.ParSeqLike import scala.collection.parallel.Combiner -import scala.collection.GenSeq - - - - - /** A mutable variant of `ParSeq`. * @@ -57,18 +50,3 @@ object ParSeq extends ParFactory[ParSeq] { def newCombiner[T]: Combiner[T, ParSeq[T]] = ParArrayCombiner[T] } - - - - - - - - - - - - - - - diff --git a/src/library/scala/collection/parallel/mutable/ParSet.scala b/src/library/scala/collection/parallel/mutable/ParSet.scala index d8f821746c..9367f1424d 100644 --- a/src/library/scala/collection/parallel/mutable/ParSet.scala +++ b/src/library/scala/collection/parallel/mutable/ParSet.scala @@ -6,18 +6,11 @@ ** |/ ** \* */ - -package scala.collection.parallel.mutable - - +package scala +package collection.parallel.mutable import scala.collection.generic._ import scala.collection.parallel.Combiner -import scala.collection.GenSet - - - - /** A mutable variant of `ParSet`. * @@ -51,4 +44,3 @@ object ParSet extends ParSetFactory[ParSet] { override def newCombiner[T]: Combiner[T, ParSet[T]] = ParHashSet.newCombiner } - diff --git a/src/library/scala/collection/parallel/mutable/ParSetLike.scala b/src/library/scala/collection/parallel/mutable/ParSetLike.scala index 609888f1a9..13af5ed649 100644 --- a/src/library/scala/collection/parallel/mutable/ParSetLike.scala +++ b/src/library/scala/collection/parallel/mutable/ParSetLike.scala @@ -6,21 +6,15 @@ ** |/ ** \* */ - -package scala.collection +package scala +package collection package parallel.mutable - - -import scala.collection.mutable.Set -import scala.collection.mutable.Builder import scala.collection.mutable.Cloneable import scala.collection.GenSetLike import scala.collection.generic.Growable import scala.collection.generic.Shrinkable - - /** A template trait for mutable parallel sets. This trait is mixed in with concrete * parallel sets to override the representation type. * @@ -54,43 +48,3 @@ self => // note: should not override toSet } - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/library/scala/collection/parallel/mutable/ParTrieMap.scala b/src/library/scala/collection/parallel/mutable/ParTrieMap.scala index 61a50a124d..a1dc37cec9 100644 --- a/src/library/scala/collection/parallel/mutable/ParTrieMap.scala +++ b/src/library/scala/collection/parallel/mutable/ParTrieMap.scala @@ -6,9 +6,8 @@ ** |/ ** \* */ -package scala.collection.parallel.mutable - - +package scala +package collection.parallel.mutable import scala.collection.generic._ import scala.collection.parallel.Combiner @@ -23,8 +22,6 @@ import scala.collection.concurrent.INode import scala.collection.concurrent.TrieMap import scala.collection.concurrent.TrieMapIterator - - /** Parallel TrieMap collection. * * It has its bulk operations parallelized, but uses the snapshot operation @@ -116,10 +113,8 @@ extends ParMap[K, V] def shouldSplitFurther = howmany > 1 override def merge(that: Size) = result = result + that.result } - } - private[collection] class ParTrieMapSplitter[K, V](lev: Int, ct: TrieMap[K, V], mustInit: Boolean) extends TrieMapIterator[K, V](lev, ct, mustInit) with IterableSplitter[(K, V)] @@ -136,7 +131,7 @@ extends TrieMapIterator[K, V](lev, ct, mustInit) } def dup = { - val it = newIterator(0, ct, false) + val it = newIterator(0, ct, _mustInit = false) dupTo(it) it.iterated = this.iterated it @@ -154,7 +149,6 @@ extends TrieMapIterator[K, V](lev, ct, mustInit) def remaining: Int = totalsize - iterated } - /** Only used within the `ParTrieMap`. */ private[mutable] trait ParTrieMapCombiner[K, V] extends Combiner[(K, V), ParTrieMap[K, V]] { @@ -172,24 +166,11 @@ private[mutable] trait ParTrieMapCombiner[K, V] extends Combiner[(K, V), ParTrie } override def canBeShared = true - } - object ParTrieMap extends ParMapFactory[ParTrieMap] { - def empty[K, V]: ParTrieMap[K, V] = new ParTrieMap[K, V] - def newCombiner[K, V]: Combiner[(K, V), ParTrieMap[K, V]] = new ParTrieMap[K, V] implicit def canBuildFrom[K, V]: CanCombineFrom[Coll, (K, V), ParTrieMap[K, V]] = new CanCombineFromMap[K, V] - } - - - - - - - - diff --git a/src/library/scala/collection/parallel/mutable/ResizableParArrayCombiner.scala b/src/library/scala/collection/parallel/mutable/ResizableParArrayCombiner.scala index dc31d1bc25..79322c85b1 100644 --- a/src/library/scala/collection/parallel/mutable/ResizableParArrayCombiner.scala +++ b/src/library/scala/collection/parallel/mutable/ResizableParArrayCombiner.scala @@ -6,7 +6,8 @@ ** |/ ** \* */ -package scala.collection.parallel.mutable +package scala +package collection.parallel.mutable @@ -26,7 +27,7 @@ trait ResizableParArrayCombiner[T] extends LazyCombiner[T, ParArray[T], ExposedA override def sizeHint(sz: Int) = if (chain.length == 1) chain(0).sizeHint(sz) // public method with private[mutable] type ExposedArrayBuffer in parameter type; cannot be overridden. - def newLazyCombiner(c: ArrayBuffer[ExposedArrayBuffer[T]]) = ResizableParArrayCombiner(c) + final def newLazyCombiner(c: ArrayBuffer[ExposedArrayBuffer[T]]) = ResizableParArrayCombiner(c) def allocateAndCopy = if (chain.size > 1) { val arrayseq = new ArraySeq[T](size) diff --git a/src/library/scala/collection/parallel/mutable/UnrolledParArrayCombiner.scala b/src/library/scala/collection/parallel/mutable/UnrolledParArrayCombiner.scala index c3a379485d..d1379cde11 100644 --- a/src/library/scala/collection/parallel/mutable/UnrolledParArrayCombiner.scala +++ b/src/library/scala/collection/parallel/mutable/UnrolledParArrayCombiner.scala @@ -6,7 +6,8 @@ ** |/ ** \* */ -package scala.collection.parallel.mutable +package scala +package collection.parallel.mutable import scala.collection.generic.Sizing import scala.collection.mutable.ArraySeq @@ -19,6 +20,7 @@ import scala.collection.parallel.Combiner import scala.collection.parallel.Task import scala.reflect.ClassTag +// Todo -- revisit whether inheritance is the best way to achieve this functionality private[mutable] class DoublingUnrolledBuffer[T](implicit t: ClassTag[T]) extends UnrolledBuffer[T]()(t) { override def calcNextLength(sz: Int) = if (sz < 10000) sz * 2 else sz protected override def newUnrolled = new Unrolled[T](0, new Array[T](4), null, this) @@ -47,7 +49,7 @@ extends Combiner[T, ParArray[T]] { } def clear() { - buff.clear + buff.clear() } override def sizeHint(sz: Int) = { @@ -69,7 +71,8 @@ extends Combiner[T, ParArray[T]] { class CopyUnrolledToArray(array: Array[Any], offset: Int, howmany: Int) extends Task[Unit, CopyUnrolledToArray] { - var result = (); + var result = () + def leaf(prev: Option[Unit]) = if (howmany > 0) { var totalleft = howmany val (startnode, startpos) = findStart(offset) diff --git a/src/library/scala/collection/parallel/mutable/package.scala b/src/library/scala/collection/parallel/mutable/package.scala index 2494d0907e..81121d9398 100644 --- a/src/library/scala/collection/parallel/mutable/package.scala +++ b/src/library/scala/collection/parallel/mutable/package.scala @@ -6,7 +6,8 @@ ** |/ ** \* */ -package scala.collection.parallel +package scala +package collection.parallel import scala.collection.mutable.ArrayBuffer import scala.collection.mutable.ArraySeq diff --git a/src/library/scala/collection/parallel/package.scala b/src/library/scala/collection/parallel/package.scala index 988886b4ea..91c54fa8f1 100644 --- a/src/library/scala/collection/parallel/package.scala +++ b/src/library/scala/collection/parallel/package.scala @@ -41,9 +41,7 @@ package object parallel { private[parallel] def outofbounds(idx: Int) = throw new IndexOutOfBoundsException(idx.toString) - private[parallel] def getTaskSupport: TaskSupport = - if (scala.util.Properties.isJavaAtLeast("1.6")) new ForkJoinTaskSupport - else new ThreadPoolTaskSupport + private[parallel] def getTaskSupport: TaskSupport = new ExecutionContextTaskSupport val defaultTaskSupport: TaskSupport = getTaskSupport @@ -55,43 +53,52 @@ package object parallel { c } - /* implicit conversions */ - - implicit def factory2ops[From, Elem, To](bf: CanBuildFrom[From, Elem, To]) = new FactoryOps[From, Elem, To] { - def isParallel = bf.isInstanceOf[Parallel] - def asParallel = bf.asInstanceOf[CanCombineFrom[From, Elem, To]] - def ifParallel[R](isbody: CanCombineFrom[From, Elem, To] => R) = new Otherwise[R] { - def otherwise(notbody: => R) = if (isParallel) isbody(asParallel) else notbody - } - } - implicit def traversable2ops[T](t: scala.collection.GenTraversableOnce[T]) = new TraversableOps[T] { - def isParallel = t.isInstanceOf[Parallel] - def isParIterable = t.isInstanceOf[ParIterable[_]] - def asParIterable = t.asInstanceOf[ParIterable[T]] - def isParSeq = t.isInstanceOf[ParSeq[_]] - def asParSeq = t.asInstanceOf[ParSeq[T]] - def ifParSeq[R](isbody: ParSeq[T] => R) = new Otherwise[R] { - def otherwise(notbody: => R) = if (isParallel) isbody(asParSeq) else notbody - } - def toParArray = if (t.isInstanceOf[ParArray[_]]) t.asInstanceOf[ParArray[T]] else { - val it = t.toIterator - val cb = mutable.ParArrayCombiner[T]() - while (it.hasNext) cb += it.next - cb.result - } - } - implicit def throwable2ops(self: Throwable) = new ThrowableOps { - def alongWith(that: Throwable) = (self, that) match { - case (self: CompositeThrowable, that: CompositeThrowable) => new CompositeThrowable(self.throwables ++ that.throwables) - case (self: CompositeThrowable, _) => new CompositeThrowable(self.throwables + that) - case (_, that: CompositeThrowable) => new CompositeThrowable(that.throwables + self) - case _ => new CompositeThrowable(Set(self, that)) + /** Adds toParArray method to collection classes. */ + implicit class CollectionsHaveToParArray[C, T](c: C)(implicit asGto: C => scala.collection.GenTraversableOnce[T]) { + def toParArray = { + val t = asGto(c) + if (t.isInstanceOf[ParArray[_]]) t.asInstanceOf[ParArray[T]] + else { + val it = t.toIterator + val cb = mutable.ParArrayCombiner[T]() + while (it.hasNext) cb += it.next + cb.result + } } } } package parallel { + /** Implicit conversions used in the implementation of parallel collections. */ + private[collection] object ParallelCollectionImplicits { + implicit def factory2ops[From, Elem, To](bf: CanBuildFrom[From, Elem, To]) = new FactoryOps[From, Elem, To] { + def isParallel = bf.isInstanceOf[Parallel] + def asParallel = bf.asInstanceOf[CanCombineFrom[From, Elem, To]] + def ifParallel[R](isbody: CanCombineFrom[From, Elem, To] => R) = new Otherwise[R] { + def otherwise(notbody: => R) = if (isParallel) isbody(asParallel) else notbody + } + } + implicit def traversable2ops[T](t: scala.collection.GenTraversableOnce[T]) = new TraversableOps[T] { + def isParallel = t.isInstanceOf[Parallel] + def isParIterable = t.isInstanceOf[ParIterable[_]] + def asParIterable = t.asInstanceOf[ParIterable[T]] + def isParSeq = t.isInstanceOf[ParSeq[_]] + def asParSeq = t.asInstanceOf[ParSeq[T]] + def ifParSeq[R](isbody: ParSeq[T] => R) = new Otherwise[R] { + def otherwise(notbody: => R) = if (isParallel) isbody(asParSeq) else notbody + } + } + implicit def throwable2ops(self: Throwable) = new ThrowableOps { + def alongWith(that: Throwable) = (self, that) match { + case (self: CompositeThrowable, that: CompositeThrowable) => new CompositeThrowable(self.throwables ++ that.throwables) + case (self: CompositeThrowable, _) => new CompositeThrowable(self.throwables + that) + case (_, that: CompositeThrowable) => new CompositeThrowable(that.throwables + self) + case _ => new CompositeThrowable(Set(self, that)) + } + } + } + trait FactoryOps[From, Elem, To] { trait Otherwise[R] { def otherwise(notbody: => R): R @@ -113,10 +120,11 @@ package parallel { def isParSeq: Boolean def asParSeq: ParSeq[T] def ifParSeq[R](isbody: ParSeq[T] => R): Otherwise[R] - def toParArray: ParArray[T] } + @deprecated("This trait will be removed.", "2.11.0") trait ThrowableOps { + @deprecated("This method will be removed.", "2.11.0") def alongWith(that: Throwable): Throwable } @@ -135,9 +143,8 @@ package parallel { } /** Composite throwable - thrown when multiple exceptions are thrown at the same time. */ - final case class CompositeThrowable( - val throwables: Set[Throwable] - ) extends Exception( + @deprecated("This class will be removed.", "2.11.0") + final case class CompositeThrowable(throwables: Set[Throwable]) extends Exception( "Multiple exceptions thrown during a parallel computation: " + throwables.map(t => t + "\n" + t.getStackTrace.take(10).++("...").mkString("\n")).mkString("\n\n") ) diff --git a/src/library/scala/collection/script/Location.scala b/src/library/scala/collection/script/Location.scala index cd64fa2d73..bed74bf9ca 100644 --- a/src/library/scala/collection/script/Location.scala +++ b/src/library/scala/collection/script/Location.scala @@ -6,7 +6,8 @@ ** |/ ** \* */ -package scala.collection +package scala +package collection package script /** Class `Location` describes locations in messages implemented by @@ -17,8 +18,17 @@ package script * @since 2.8 */ +@deprecated("Scripting is deprecated.", "2.11.0") sealed abstract class Location + +@deprecated("Scripting is deprecated.", "2.11.0") case object Start extends Location + +@deprecated("Scripting is deprecated.", "2.11.0") case object End extends Location + +@deprecated("Scripting is deprecated.", "2.11.0") case object NoLo extends Location + +@deprecated("Scripting is deprecated.", "2.11.0") case class Index(n: Int) extends Location diff --git a/src/library/scala/collection/script/Message.scala b/src/library/scala/collection/script/Message.scala index 2ab7ea726a..3fc2a0ec7e 100644 --- a/src/library/scala/collection/script/Message.scala +++ b/src/library/scala/collection/script/Message.scala @@ -6,7 +6,8 @@ ** |/ ** \* */ -package scala.collection +package scala +package collection package script import mutable.ArrayBuffer @@ -20,6 +21,7 @@ import mutable.ArrayBuffer * @version 1.0, 08/07/2003 * @since 2.8 */ +@deprecated("Scripting is deprecated.", "2.11.0") trait Message[+A] /** This observable update refers to inclusion operations that add new elements @@ -28,6 +30,7 @@ trait Message[+A] * @author Matthias Zenger * @version 1.0, 08/07/2003 */ +@deprecated("Scripting is deprecated.", "2.11.0") case class Include[+A](location: Location, elem: A) extends Message[A] { def this(elem: A) = this(NoLo, elem) } @@ -38,6 +41,7 @@ case class Include[+A](location: Location, elem: A) extends Message[A] { * @author Matthias Zenger * @version 1.0, 08/07/2003 */ +@deprecated("Scripting is deprecated.", "2.11.0") case class Update[+A](location: Location, elem: A) extends Message[A] { def this(elem: A) = this(NoLo, elem) } @@ -48,6 +52,7 @@ case class Update[+A](location: Location, elem: A) extends Message[A] { * @author Matthias Zenger * @version 1.0, 08/07/2003 */ +@deprecated("Scripting is deprecated.", "2.11.0") case class Remove[+A](location: Location, elem: A) extends Message[A] { def this(elem: A) = this(NoLo, elem) } @@ -57,6 +62,7 @@ case class Remove[+A](location: Location, elem: A) extends Message[A] { * @author Matthias Zenger * @version 1.0, 08/07/2003 */ +@deprecated("Scripting is deprecated.", "2.11.0") case class Reset[+A]() extends Message[A] /** Objects of this class represent compound messages consisting @@ -65,11 +71,12 @@ case class Reset[+A]() extends Message[A] * @author Matthias Zenger * @version 1.0, 10/05/2004 */ +@deprecated("Scripting is deprecated.", "2.11.0") class Script[A] extends ArrayBuffer[Message[A]] with Message[A] { override def toString(): String = { var res = "Script(" - var it = this.iterator + val it = this.iterator var i = 1 while (it.hasNext) { if (i > 1) diff --git a/src/library/scala/collection/script/Scriptable.scala b/src/library/scala/collection/script/Scriptable.scala index ceaf19a464..4db75ddd3e 100644 --- a/src/library/scala/collection/script/Scriptable.scala +++ b/src/library/scala/collection/script/Scriptable.scala @@ -6,7 +6,8 @@ ** |/ ** \* */ -package scala.collection +package scala +package collection package script /** Classes that mix in the `Scriptable` class allow messages to be sent to @@ -16,6 +17,7 @@ package script * @version 1.0, 09/05/2004 * @since 2.8 */ +@deprecated("Scripting is deprecated.", "2.11.0") trait Scriptable[A] { /** Send a message to this scriptable object. */ diff --git a/src/library/scala/compat/Platform.scala b/src/library/scala/compat/Platform.scala index 88cb1506ae..875d811b9b 100644 --- a/src/library/scala/compat/Platform.scala +++ b/src/library/scala/compat/Platform.scala @@ -6,9 +6,8 @@ ** |/ ** \* */ - - -package scala.compat +package scala +package compat import java.lang.System diff --git a/src/library/scala/concurrent/Awaitable.scala b/src/library/scala/concurrent/Awaitable.scala index 652a23471f..dff83874ba 100644 --- a/src/library/scala/concurrent/Awaitable.scala +++ b/src/library/scala/concurrent/Awaitable.scala @@ -17,7 +17,7 @@ import scala.concurrent.duration.Duration /** * An object that may eventually be completed with a result value of type `T` which may be * awaited using blocking methods. - * + * * The [[Await]] object provides methods that allow accessing the result of an `Awaitable` * by blocking the current thread until the `Awaitable` has been completed or a timeout has * occurred. @@ -26,9 +26,9 @@ trait Awaitable[+T] { /** * Await the "completed" state of this `Awaitable`. - * + * * '''''This method should not be called directly; use [[Await.ready]] instead.''''' - * + * * @param atMost * maximum wait time, which may be negative (no waiting is done), * [[scala.concurrent.duration.Duration.Inf Duration.Inf]] for unbounded waiting, or a finite positive @@ -41,12 +41,12 @@ trait Awaitable[+T] { @throws(classOf[TimeoutException]) @throws(classOf[InterruptedException]) def ready(atMost: Duration)(implicit permit: CanAwait): this.type - + /** * Await and return the result (of type `T`) of this `Awaitable`. - * + * * '''''This method should not be called directly; use [[Await.result]] instead.''''' - * + * * @param atMost * maximum wait time, which may be negative (no waiting is done), * [[scala.concurrent.duration.Duration.Inf Duration.Inf]] for unbounded waiting, or a finite positive diff --git a/src/library/scala/concurrent/BatchingExecutor.scala b/src/library/scala/concurrent/BatchingExecutor.scala new file mode 100644 index 0000000000..a0d7aaea47 --- /dev/null +++ b/src/library/scala/concurrent/BatchingExecutor.scala @@ -0,0 +1,117 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +package scala.concurrent + +import java.util.concurrent.Executor +import scala.annotation.tailrec + +/** + * Mixin trait for an Executor + * which groups multiple nested `Runnable.run()` calls + * into a single Runnable passed to the original + * Executor. This can be a useful optimization + * because it bypasses the original context's task + * queue and keeps related (nested) code on a single + * thread which may improve CPU affinity. However, + * if tasks passed to the Executor are blocking + * or expensive, this optimization can prevent work-stealing + * and make performance worse. Also, some ExecutionContext + * may be fast enough natively that this optimization just + * adds overhead. + * The default ExecutionContext.global is already batching + * or fast enough not to benefit from it; while + * `fromExecutor` and `fromExecutorService` do NOT add + * this optimization since they don't know whether the underlying + * executor will benefit from it. + * A batching executor can create deadlocks if code does + * not use `scala.concurrent.blocking` when it should, + * because tasks created within other tasks will block + * on the outer task completing. + * This executor may run tasks in any order, including LIFO order. + * There are no ordering guarantees. + * + * WARNING: The underlying Executor's execute-method must not execute the submitted Runnable + * in the calling thread synchronously. It must enqueue/handoff the Runnable. + */ +private[concurrent] trait BatchingExecutor extends Executor { + + // invariant: if "_tasksLocal.get ne null" then we are inside BatchingRunnable.run; if it is null, we are outside + private val _tasksLocal = new ThreadLocal[List[Runnable]]() + + private class Batch(val initial: List[Runnable]) extends Runnable with BlockContext { + private var parentBlockContext: BlockContext = _ + // this method runs in the delegate ExecutionContext's thread + override def run(): Unit = { + require(_tasksLocal.get eq null) + + val prevBlockContext = BlockContext.current + BlockContext.withBlockContext(this) { + try { + parentBlockContext = prevBlockContext + + @tailrec def processBatch(batch: List[Runnable]): Unit = batch match { + case Nil => () + case head :: tail => + _tasksLocal set tail + try { + head.run() + } catch { + case t: Throwable => + // if one task throws, move the + // remaining tasks to another thread + // so we can throw the exception + // up to the invoking executor + val remaining = _tasksLocal.get + _tasksLocal set Nil + unbatchedExecute(new Batch(remaining)) //TODO what if this submission fails? + throw t // rethrow + } + processBatch(_tasksLocal.get) // since head.run() can add entries, always do _tasksLocal.get here + } + + processBatch(initial) + } finally { + _tasksLocal.remove() + parentBlockContext = null + } + } + } + + override def blockOn[T](thunk: => T)(implicit permission: CanAwait): T = { + // if we know there will be blocking, we don't want to keep tasks queued up because it could deadlock. + { + val tasks = _tasksLocal.get + _tasksLocal set Nil + if ((tasks ne null) && tasks.nonEmpty) + unbatchedExecute(new Batch(tasks)) + } + + // now delegate the blocking to the previous BC + require(parentBlockContext ne null) + parentBlockContext.blockOn(thunk) + } + } + + protected def unbatchedExecute(r: Runnable): Unit + + override def execute(runnable: Runnable): Unit = { + if (batchable(runnable)) { // If we can batch the runnable + _tasksLocal.get match { + case null => unbatchedExecute(new Batch(List(runnable))) // If we aren't in batching mode yet, enqueue batch + case some => _tasksLocal.set(runnable :: some) // If we are already in batching mode, add to batch + } + } else unbatchedExecute(runnable) // If not batchable, just delegate to underlying + } + + /** Override this to define which runnables will be batched. */ + def batchable(runnable: Runnable): Boolean = runnable match { + case _: OnCompleteRunnable => true + case _ => false + } +} diff --git a/src/library/scala/concurrent/ExecutionContext.scala b/src/library/scala/concurrent/ExecutionContext.scala index b4af161c3c..a1e94c8876 100644 --- a/src/library/scala/concurrent/ExecutionContext.scala +++ b/src/library/scala/concurrent/ExecutionContext.scala @@ -14,19 +14,60 @@ import scala.annotation.implicitNotFound import scala.util.Try /** - * An `ExecutionContext` is an abstraction over an entity that can execute program logic. + * An `ExecutionContext` can execute program logic asynchronously, + * typically but not necessarily on a thread pool. + * + * A general purpose `ExecutionContext` must be asynchronous in executing + * any `Runnable` that is passed into its `execute`-method. A special purpose + * `ExecutionContext` may be synchronous but must only be passed to code that + * is explicitly safe to be run using a synchronously executing `ExecutionContext`. + * + * APIs such as `Future.onComplete` require you to provide a callback + * and an implicit `ExecutionContext`. The implicit `ExecutionContext` + * will be used to execute the callback. + * + * It is possible to simply import + * `scala.concurrent.ExecutionContext.Implicits.global` to obtain an + * implicit `ExecutionContext`. This global context is a reasonable + * default thread pool. + * + * However, application developers should carefully consider where they + * want to set policy; ideally, one place per application (or per + * logically-related section of code) will make a decision about + * which `ExecutionContext` to use. That is, you might want to avoid + * hardcoding `scala.concurrent.ExecutionContext.Implicits.global` all + * over the place in your code. + * One approach is to add `(implicit ec: ExecutionContext)` + * to methods which need an `ExecutionContext`. Then import a specific + * context in one place for the entire application or module, + * passing it implicitly to individual methods. + * + * A custom `ExecutionContext` may be appropriate to execute code + * which blocks on IO or performs long-running computations. + * `ExecutionContext.fromExecutorService` and `ExecutionContext.fromExecutor` + * are good ways to create a custom `ExecutionContext`. + * + * The intent of `ExecutionContext` is to lexically scope code execution. + * That is, each method, class, file, package, or application determines + * how to run its own code. This avoids issues such as running + * application callbacks on a thread pool belonging to a networking library. + * The size of a networking library's thread pool can be safely configured, + * knowing that only that library's network operations will be affected. + * Application callback execution can be configured separately. */ -@implicitNotFound("Cannot find an implicit ExecutionContext, either import scala.concurrent.ExecutionContext.Implicits.global or use a custom one") +@implicitNotFound("""Cannot find an implicit ExecutionContext. You might pass +an (implicit ec: ExecutionContext) parameter to your method +or import scala.concurrent.ExecutionContext.Implicits.global.""") trait ExecutionContext { - + /** Runs a block of code on this execution context. */ def execute(runnable: Runnable): Unit - + /** Reports that an asynchronous computation failed. */ - def reportFailure(t: Throwable): Unit - + def reportFailure(@deprecatedName('t) cause: Throwable): Unit + /** Prepares for the execution of a task. Returns the prepared * execution context. A valid implementation of `prepare` is one * that simply returns `this`. @@ -62,7 +103,7 @@ object ExecutionContext { */ implicit lazy val global: ExecutionContextExecutor = impl.ExecutionContextImpl.fromExecutor(null: Executor) } - + /** Creates an `ExecutionContext` from the given `ExecutorService`. */ def fromExecutorService(e: ExecutorService, reporter: Throwable => Unit): ExecutionContextExecutorService = @@ -71,7 +112,7 @@ object ExecutionContext { /** Creates an `ExecutionContext` from the given `ExecutorService` with the default Reporter. */ def fromExecutorService(e: ExecutorService): ExecutionContextExecutorService = fromExecutorService(e, defaultReporter) - + /** Creates an `ExecutionContext` from the given `Executor`. */ def fromExecutor(e: Executor, reporter: Throwable => Unit): ExecutionContextExecutor = @@ -80,10 +121,10 @@ object ExecutionContext { /** Creates an `ExecutionContext` from the given `Executor` with the default Reporter. */ def fromExecutor(e: Executor): ExecutionContextExecutor = fromExecutor(e, defaultReporter) - + /** The default reporter simply prints the stack trace of the `Throwable` to System.err. */ - def defaultReporter: Throwable => Unit = (t: Throwable) => t.printStackTrace() + def defaultReporter: Throwable => Unit = _.printStackTrace() } diff --git a/src/library/scala/concurrent/Future.scala b/src/library/scala/concurrent/Future.scala index b2c09ec53e..4ed0687334 100644 --- a/src/library/scala/concurrent/Future.scala +++ b/src/library/scala/concurrent/Future.scala @@ -29,11 +29,11 @@ import scala.reflect.ClassTag /** The trait that represents futures. * - * Asynchronous computations that yield futures are created with the `future` call: + * Asynchronous computations that yield futures are created with the `Future` call: * * {{{ * val s = "Hello" - * val f: Future[String] = future { + * val f: Future[String] = Future { * s + " future!" * } * f onSuccess { @@ -67,11 +67,11 @@ import scala.reflect.ClassTag * Example: * * {{{ - * val f = future { 5 } - * val g = future { 3 } + * val f = Future { 5 } + * val g = Future { 3 } * val h = for { * x: Int <- f // returns Future(5) - * y: Int <- g // returns Future(5) + * y: Int <- g // returns Future(3) * } yield x + y * }}} * @@ -131,9 +131,9 @@ trait Future[+T] extends Awaitable[T] { * $multipleCallbacks * $callbackInContext */ - def onFailure[U](callback: PartialFunction[Throwable, U])(implicit executor: ExecutionContext): Unit = onComplete { + def onFailure[U](@deprecatedName('callback) pf: PartialFunction[Throwable, U])(implicit executor: ExecutionContext): Unit = onComplete { case Failure(t) => - callback.applyOrElse[Throwable, Any](t, Predef.conforms[Throwable]) // Exploiting the cached function to avoid MatchError + pf.applyOrElse[Throwable, Any](t, Predef.conforms[Throwable]) // Exploiting the cached function to avoid MatchError case _ => } @@ -146,7 +146,7 @@ trait Future[+T] extends Awaitable[T] { * $multipleCallbacks * $callbackInContext */ - def onComplete[U](func: Try[T] => U)(implicit executor: ExecutionContext): Unit + def onComplete[U](@deprecatedName('func) f: Try[T] => U)(implicit executor: ExecutionContext): Unit /* Miscellaneous */ @@ -266,16 +266,16 @@ trait Future[+T] extends Awaitable[T] { * * Example: * {{{ - * val f = future { 5 } + * val f = Future { 5 } * val g = f filter { _ % 2 == 1 } * val h = f filter { _ % 2 == 0 } * Await.result(g, Duration.Zero) // evaluates to 5 * Await.result(h, Duration.Zero) // throw a NoSuchElementException * }}} */ - def filter(pred: T => Boolean)(implicit executor: ExecutionContext): Future[T] = + def filter(@deprecatedName('pred) p: T => Boolean)(implicit executor: ExecutionContext): Future[T] = map { - r => if (pred(r)) r else throw new NoSuchElementException("Future.filter predicate is not satisfied") + r => if (p(r)) r else throw new NoSuchElementException("Future.filter predicate is not satisfied") } /** Used by for-comprehensions. @@ -291,7 +291,7 @@ trait Future[+T] extends Awaitable[T] { * * Example: * {{{ - * val f = future { -5 } + * val f = Future { -5 } * val g = f collect { * case x if x < 0 => -x * } @@ -314,9 +314,9 @@ trait Future[+T] extends Awaitable[T] { * Example: * * {{{ - * future (6 / 0) recover { case e: ArithmeticException => 0 } // result: 0 - * future (6 / 0) recover { case e: NotFoundException => 0 } // result: exception - * future (6 / 2) recover { case e: ArithmeticException => 0 } // result: 3 + * Future (6 / 0) recover { case e: ArithmeticException => 0 } // result: 0 + * Future (6 / 0) recover { case e: NotFoundException => 0 } // result: exception + * Future (6 / 2) recover { case e: ArithmeticException => 0 } // result: 3 * }}} */ def recover[U >: T](pf: PartialFunction[Throwable, U])(implicit executor: ExecutionContext): Future[U] = { @@ -334,8 +334,8 @@ trait Future[+T] extends Awaitable[T] { * Example: * * {{{ - * val f = future { Int.MaxValue } - * future (6 / 0) recoverWith { case e: ArithmeticException => f } // result: Int.MaxValue + * val f = Future { Int.MaxValue } + * Future (6 / 0) recoverWith { case e: ArithmeticException => f } // result: Int.MaxValue * }}} */ def recoverWith[U >: T](pf: PartialFunction[Throwable, Future[U]])(implicit executor: ExecutionContext): Future[U] = { @@ -373,8 +373,8 @@ trait Future[+T] extends Awaitable[T] { * * Example: * {{{ - * val f = future { sys.error("failed") } - * val g = future { 5 } + * val f = Future { sys.error("failed") } + * val g = Future { 5 } * val h = f fallbackTo g * Await.result(h, Duration.Zero) // evaluates to 5 * }}} @@ -419,7 +419,7 @@ trait Future[+T] extends Awaitable[T] { * The following example prints out `5`: * * {{{ - * val f = future { 5 } + * val f = Future { 5 } * f andThen { * case r => sys.error("runtime exception") * } andThen { @@ -473,24 +473,31 @@ object Future { */ def successful[T](result: T): Future[T] = Promise.successful(result).future + /** Creates an already completed Future with the specified result or exception. + * + * @tparam T the type of the value in the promise + * @return the newly created `Future` object + */ + def fromTry[T](result: Try[T]): Future[T] = Promise.fromTry(result).future + /** Starts an asynchronous computation and returns a `Future` object with the result of that computation. * * The result becomes available once the asynchronous computation is completed. * * @tparam T the type of the result * @param body the asychronous computation - * @param execctx the execution context on which the future is run + * @param executor the execution context on which the future is run * @return the `Future` holding the result of the computation */ - def apply[T](body: =>T)(implicit execctx: ExecutionContext): Future[T] = impl.Future(body) + def apply[T](body: =>T)(implicit @deprecatedName('execctx) executor: ExecutionContext): Future[T] = impl.Future(body) - /** Simple version of `Futures.traverse`. Transforms a `TraversableOnce[Future[A]]` into a `Future[TraversableOnce[A]]`. + /** Simple version of `Future.traverse`. Transforms a `TraversableOnce[Future[A]]` into a `Future[TraversableOnce[A]]`. * Useful for reducing many `Future`s into a single `Future`. */ - def sequence[A, M[_] <: TraversableOnce[_]](in: M[Future[A]])(implicit cbf: CanBuildFrom[M[Future[A]], A, M[A]], executor: ExecutionContext): Future[M[A]] = { - in.foldLeft(Promise.successful(cbf(in)).future) { - (fr, fa) => for (r <- fr; a <- fa.asInstanceOf[Future[A]]) yield (r += a) - } map (_.result) + def sequence[A, M[X] <: TraversableOnce[X]](in: M[Future[A]])(implicit cbf: CanBuildFrom[M[Future[A]], A, M[A]], executor: ExecutionContext): Future[M[A]] = { + in.foldLeft(successful(cbf(in))) { + (fr, fa) => for (r <- fr; a <- fa) yield (r += a) + } map (_.result()) } /** Returns a new `Future` to the result of the first future in the list that is completed. @@ -504,15 +511,15 @@ object Future { /** Returns a `Future` that will hold the optional result of the first `Future` with a result that matches the predicate. */ - def find[T](futurestravonce: TraversableOnce[Future[T]])(predicate: T => Boolean)(implicit executor: ExecutionContext): Future[Option[T]] = { - val futures = futurestravonce.toBuffer - if (futures.isEmpty) Promise.successful[Option[T]](None).future + def find[T](@deprecatedName('futurestravonce) futures: TraversableOnce[Future[T]])(@deprecatedName('predicate) p: T => Boolean)(implicit executor: ExecutionContext): Future[Option[T]] = { + val futuresBuffer = futures.toBuffer + if (futuresBuffer.isEmpty) successful[Option[T]](None) else { val result = Promise[Option[T]]() - val ref = new AtomicInteger(futures.size) + val ref = new AtomicInteger(futuresBuffer.size) val search: Try[T] => Unit = v => try { v match { - case Success(r) => if (predicate(r)) result tryComplete Success(Some(r)) + case Success(r) if p(r) => result tryComplete Success(Some(r)) case _ => } } finally { @@ -521,7 +528,7 @@ object Future { } } - futures.foreach(_ onComplete search) + futuresBuffer.foreach(_ onComplete search) result.future } @@ -537,9 +544,9 @@ object Future { * val result = Await.result(Future.fold(futures)(0)(_ + _), 5 seconds) * }}} */ - def fold[T, R](futures: TraversableOnce[Future[T]])(zero: R)(foldFun: (R, T) => R)(implicit executor: ExecutionContext): Future[R] = { - if (futures.isEmpty) Future.successful(zero) - else sequence(futures).map(_.foldLeft(zero)(foldFun)) + def fold[T, R](futures: TraversableOnce[Future[T]])(zero: R)(@deprecatedName('foldFun) op: (R, T) => R)(implicit executor: ExecutionContext): Future[R] = { + if (futures.isEmpty) successful(zero) + else sequence(futures).map(_.foldLeft(zero)(op)) } /** Initiates a fold over the supplied futures where the fold-zero is the result value of the `Future` that's completed first. @@ -550,7 +557,7 @@ object Future { * }}} */ def reduce[T, R >: T](futures: TraversableOnce[Future[T]])(op: (R, T) => R)(implicit executor: ExecutionContext): Future[R] = { - if (futures.isEmpty) Future.failed(new NoSuchElementException("reduce attempted on empty collection")) + if (futures.isEmpty) failed(new NoSuchElementException("reduce attempted on empty collection")) else sequence(futures).map(_ reduceLeft op) } @@ -562,11 +569,11 @@ object Future { * val myFutureList = Future.traverse(myList)(x => Future(myFunc(x))) * }}} */ - def traverse[A, B, M[_] <: TraversableOnce[_]](in: M[A])(fn: A => Future[B])(implicit cbf: CanBuildFrom[M[A], B, M[B]], executor: ExecutionContext): Future[M[B]] = - in.foldLeft(Promise.successful(cbf(in)).future) { (fr, a) => - val fb = fn(a.asInstanceOf[A]) + def traverse[A, B, M[X] <: TraversableOnce[X]](in: M[A])(fn: A => Future[B])(implicit cbf: CanBuildFrom[M[A], B, M[B]], executor: ExecutionContext): Future[M[B]] = + in.foldLeft(successful(cbf(in))) { (fr, a) => + val fb = fn(a) for (r <- fr; b <- fb) yield (r += b) - }.map(_.result) + }.map(_.result()) // This is used to run callbacks which are internal // to scala.concurrent; our own callbacks are only @@ -587,111 +594,11 @@ object Future { // by just not ever using it itself. scala.concurrent // doesn't need to create defaultExecutionContext as // a side effect. - private[concurrent] object InternalCallbackExecutor extends ExecutionContext with java.util.concurrent.Executor { + private[concurrent] object InternalCallbackExecutor extends ExecutionContext with BatchingExecutor { + override protected def unbatchedExecute(r: Runnable): Unit = + r.run() override def reportFailure(t: Throwable): Unit = throw new IllegalStateException("problem in scala.concurrent internal callback", t) - - /** - * The BatchingExecutor trait had to be inlined into InternalCallbackExecutor for binary compatibility. - * - * BatchingExecutor is a trait for an Executor - * which groups multiple nested `Runnable.run()` calls - * into a single Runnable passed to the original - * Executor. This can be a useful optimization - * because it bypasses the original context's task - * queue and keeps related (nested) code on a single - * thread which may improve CPU affinity. However, - * if tasks passed to the Executor are blocking - * or expensive, this optimization can prevent work-stealing - * and make performance worse. Also, some ExecutionContext - * may be fast enough natively that this optimization just - * adds overhead. - * The default ExecutionContext.global is already batching - * or fast enough not to benefit from it; while - * `fromExecutor` and `fromExecutorService` do NOT add - * this optimization since they don't know whether the underlying - * executor will benefit from it. - * A batching executor can create deadlocks if code does - * not use `scala.concurrent.blocking` when it should, - * because tasks created within other tasks will block - * on the outer task completing. - * This executor may run tasks in any order, including LIFO order. - * There are no ordering guarantees. - * - * WARNING: The underlying Executor's execute-method must not execute the submitted Runnable - * in the calling thread synchronously. It must enqueue/handoff the Runnable. - */ - // invariant: if "_tasksLocal.get ne null" then we are inside BatchingRunnable.run; if it is null, we are outside - private val _tasksLocal = new ThreadLocal[List[Runnable]]() - - private class Batch(val initial: List[Runnable]) extends Runnable with BlockContext { - private[this] var parentBlockContext: BlockContext = _ - // this method runs in the delegate ExecutionContext's thread - override def run(): Unit = { - require(_tasksLocal.get eq null) - - val prevBlockContext = BlockContext.current - BlockContext.withBlockContext(this) { - try { - parentBlockContext = prevBlockContext - - @tailrec def processBatch(batch: List[Runnable]): Unit = batch match { - case Nil => () - case head :: tail => - _tasksLocal set tail - try { - head.run() - } catch { - case t: Throwable => - // if one task throws, move the - // remaining tasks to another thread - // so we can throw the exception - // up to the invoking executor - val remaining = _tasksLocal.get - _tasksLocal set Nil - unbatchedExecute(new Batch(remaining)) //TODO what if this submission fails? - throw t // rethrow - } - processBatch(_tasksLocal.get) // since head.run() can add entries, always do _tasksLocal.get here - } - - processBatch(initial) - } finally { - _tasksLocal.remove() - parentBlockContext = null - } - } - } - - override def blockOn[T](thunk: => T)(implicit permission: CanAwait): T = { - // if we know there will be blocking, we don't want to keep tasks queued up because it could deadlock. - { - val tasks = _tasksLocal.get - _tasksLocal set Nil - if ((tasks ne null) && tasks.nonEmpty) - unbatchedExecute(new Batch(tasks)) - } - - // now delegate the blocking to the previous BC - require(parentBlockContext ne null) - parentBlockContext.blockOn(thunk) - } - } - - override def execute(runnable: Runnable): Unit = runnable match { - // If we can batch the runnable - case _: OnCompleteRunnable => - _tasksLocal.get match { - case null => unbatchedExecute(new Batch(List(runnable))) // If we aren't in batching mode yet, enqueue batch - case some => _tasksLocal.set(runnable :: some) // If we are already in batching mode, add to batch - } - - // If not batchable, just delegate to underlying - case _ => - unbatchedExecute(runnable) - } - - private def unbatchedExecute(r: Runnable): Unit = r.run() } } diff --git a/src/library/scala/concurrent/FutureTaskRunner.scala b/src/library/scala/concurrent/FutureTaskRunner.scala index eeadaddb5e..089e67cedd 100644 --- a/src/library/scala/concurrent/FutureTaskRunner.scala +++ b/src/library/scala/concurrent/FutureTaskRunner.scala @@ -1,6 +1,6 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2009-2011, LAMP/EPFL ** +** / __/ __// _ | / / / _ | (c) 2009-2013, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** @@ -10,13 +10,13 @@ package scala.concurrent import scala.language.{implicitConversions, higherKinds} -/** The `FutureTaskRunner</code> trait is a base trait of task runners +/** The `FutureTaskRunner` trait is a base trait of task runners * that provide some sort of future abstraction. * * @author Philipp Haller */ @deprecated("Use `ExecutionContext` instead.", "2.10.0") -trait FutureTaskRunner extends TaskRunner { +private[scala] trait FutureTaskRunner extends TaskRunner { /** The type of the futures that the underlying task runner supports. */ diff --git a/src/library/scala/concurrent/JavaConversions.scala b/src/library/scala/concurrent/JavaConversions.scala index d6a7c1f1bb..3d0597ca22 100644 --- a/src/library/scala/concurrent/JavaConversions.scala +++ b/src/library/scala/concurrent/JavaConversions.scala @@ -18,38 +18,6 @@ import scala.language.implicitConversions */ object JavaConversions { - @deprecated("Use `asExecutionContext` instead.", "2.10.0") - implicit def asTaskRunner(exec: ExecutorService): FutureTaskRunner = - new ThreadPoolRunner { - override protected def executor = - exec - - def shutdown() = - exec.shutdown() - } - - @deprecated("Use `asExecutionContext` instead.", "2.10.0") - implicit def asTaskRunner(exec: Executor): TaskRunner = - new TaskRunner { - type Task[T] = Runnable - - implicit def functionAsTask[T](fun: () => T): Task[T] = new Runnable { - def run() { fun() } - } - - def execute[S](task: Task[S]) { - exec.execute(task) - } - - def managedBlock(blocker: ManagedBlocker) { - blocker.block() - } - - def shutdown() { - // do nothing - } - } - /** * Creates a new `ExecutionContext` which uses the provided `ExecutorService`. */ diff --git a/src/library/scala/concurrent/Lock.scala b/src/library/scala/concurrent/Lock.scala index 4b8139702f..8d18da2d38 100644 --- a/src/library/scala/concurrent/Lock.scala +++ b/src/library/scala/concurrent/Lock.scala @@ -15,6 +15,7 @@ package scala.concurrent * @author Martin Odersky * @version 1.0, 10/03/2003 */ +@deprecated("Use java.util.concurrent.locks.Lock", "2.11.2") class Lock { var available = true diff --git a/src/library/scala/concurrent/ManagedBlocker.scala b/src/library/scala/concurrent/ManagedBlocker.scala index 7b2966c663..b5a6e21893 100644 --- a/src/library/scala/concurrent/ManagedBlocker.scala +++ b/src/library/scala/concurrent/ManagedBlocker.scala @@ -13,7 +13,7 @@ package scala.concurrent * @author Philipp Haller */ @deprecated("Use `blocking` instead.", "2.10.0") -trait ManagedBlocker { +private[scala] trait ManagedBlocker { /** * Possibly blocks the current thread, for example waiting for diff --git a/src/library/scala/concurrent/Promise.scala b/src/library/scala/concurrent/Promise.scala index 8355a73a1f..eb8044ed3b 100644 --- a/src/library/scala/concurrent/Promise.scala +++ b/src/library/scala/concurrent/Promise.scala @@ -70,7 +70,7 @@ trait Promise[T] { other onComplete { this complete _ } this } - + /** Attempts to complete this promise with the specified future, once that future is completed. * * @return This promise @@ -82,11 +82,11 @@ trait Promise[T] { /** Completes the promise with a value. * - * @param v The value to complete the promise with. + * @param value The value to complete the promise with. * * $promiseCompletion */ - def success(v: T): this.type = complete(Success(v)) + def success(@deprecatedName('v) value: T): this.type = complete(Success(value)) /** Tries to complete the promise with a value. * @@ -98,13 +98,13 @@ trait Promise[T] { /** Completes the promise with an exception. * - * @param t The throwable to complete the promise with. + * @param cause The throwable to complete the promise with. * * $allowedThrowables * * $promiseCompletion */ - def failure(t: Throwable): this.type = complete(Failure(t)) + def failure(@deprecatedName('t) cause: Throwable): this.type = complete(Failure(cause)) /** Tries to complete the promise with an exception. * @@ -112,41 +112,35 @@ trait Promise[T] { * * @return If the promise has already been completed returns `false`, or `true` otherwise. */ - def tryFailure(t: Throwable): Boolean = tryComplete(Failure(t)) + def tryFailure(@deprecatedName('t) cause: Throwable): Boolean = tryComplete(Failure(cause)) } - - object Promise { - /** Creates a promise object which can be completed with a value. - * + * * @tparam T the type of the value in the promise * @return the newly created `Promise` object */ def apply[T](): Promise[T] = new impl.Promise.DefaultPromise[T]() /** Creates an already completed Promise with the specified exception. - * + * * @tparam T the type of the value in the promise * @return the newly created `Promise` object */ - def failed[T](exception: Throwable): Promise[T] = new impl.Promise.KeptPromise[T](Failure(exception)) + def failed[T](exception: Throwable): Promise[T] = fromTry(Failure(exception)) /** Creates an already completed Promise with the specified result. - * + * * @tparam T the type of the value in the promise * @return the newly created `Promise` object */ - def successful[T](result: T): Promise[T] = new impl.Promise.KeptPromise[T](Success(result)) - -} - - - - - - - - + def successful[T](result: T): Promise[T] = fromTry(Success(result)) + /** Creates an already completed Promise with the specified result or exception. + * + * @tparam T the type of the value in the promise + * @return the newly created `Promise` object + */ + def fromTry[T](result: Try[T]): Promise[T] = new impl.Promise.KeptPromise[T](result) +} diff --git a/src/library/scala/concurrent/SyncVar.scala b/src/library/scala/concurrent/SyncVar.scala index 9ab7bcc572..d5dc3d7e3f 100644 --- a/src/library/scala/concurrent/SyncVar.scala +++ b/src/library/scala/concurrent/SyncVar.scala @@ -8,6 +8,8 @@ package scala.concurrent +import java.util.concurrent.TimeUnit + /** A class to provide safe concurrent access to a mutable cell. * All methods are synchronized. * @@ -23,14 +25,16 @@ class SyncVar[A] { value.get } - /** Waits `timeout` millis. If `timeout <= 0` just returns 0. If the system clock - * went backward, it will return 0, so it never returns negative results. - */ + /** Waits `timeout` millis. If `timeout <= 0` just returns 0. + * It never returns negative results. + */ private def waitMeasuringElapsed(timeout: Long): Long = if (timeout <= 0) 0 else { - val start = System.currentTimeMillis + val start = System.nanoTime() wait(timeout) - val elapsed = System.currentTimeMillis - start - if (elapsed < 0) 0 else elapsed + val elapsed = System.nanoTime() - start + // nanoTime should be monotonic, but it's not possible to rely on that. + // See http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6458294. + if (elapsed < 0) 0 else TimeUnit.NANOSECONDS.toMillis(elapsed) } /** Waits for this SyncVar to become defined at least for @@ -41,9 +45,9 @@ class SyncVar[A] { * @return `None` if variable is undefined after `timeout`, `Some(value)` otherwise */ def get(timeout: Long): Option[A] = synchronized { - /** Defending against the system clock going backward - * by counting time elapsed directly. Loop required - * to deal with spurious wakeups. + /* Defending against the system clock going backward + * by counting time elapsed directly. Loop required + * to deal with spurious wakeups. */ var rest = timeout while (!isDefined && rest > 0) { @@ -79,6 +83,7 @@ class SyncVar[A] { // whether or not the SyncVar is already defined. So, set has been // deprecated in order to eventually be able to make "setting" private @deprecated("Use `put` instead, as `set` is potentionally error-prone", "2.10.0") + // NOTE: Used by SBT 0.13.0-M2 and below def set(x: A): Unit = setVal(x) /** Places a value in the SyncVar. If the SyncVar already has a stored value, @@ -98,6 +103,7 @@ class SyncVar[A] { // whether or not the SyncVar is already defined. So, unset has been // deprecated in order to eventually be able to make "unsetting" private @deprecated("Use `take` instead, as `unset` is potentionally error-prone", "2.10.0") + // NOTE: Used by SBT 0.13.0-M2 and below def unset(): Unit = synchronized { isDefined = false value = None diff --git a/src/library/scala/concurrent/TaskRunner.scala b/src/library/scala/concurrent/TaskRunner.scala index a939a3f070..1ea23b35e8 100644 --- a/src/library/scala/concurrent/TaskRunner.scala +++ b/src/library/scala/concurrent/TaskRunner.scala @@ -15,7 +15,7 @@ import scala.language.{higherKinds, implicitConversions} * @author Philipp Haller */ @deprecated("Use `ExecutionContext` instead.", "2.10.0") -trait TaskRunner { +private[scala] trait TaskRunner { type Task[T] @@ -24,5 +24,4 @@ trait TaskRunner { def execute[S](task: Task[S]): Unit def shutdown(): Unit - } diff --git a/src/library/scala/concurrent/TaskRunners.scala b/src/library/scala/concurrent/TaskRunners.scala deleted file mode 100644 index e109a8abf9..0000000000 --- a/src/library/scala/concurrent/TaskRunners.scala +++ /dev/null @@ -1,36 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala.concurrent - -import java.util.concurrent.{ThreadPoolExecutor, LinkedBlockingQueue, TimeUnit} - -/** The `TaskRunners` object... - * - * @author Philipp Haller - */ -@deprecated("Use `ExecutionContext` instead.", "2.10.0") -object TaskRunners { - - implicit val threadRunner: FutureTaskRunner = - new ThreadRunner - - implicit val threadPoolRunner: FutureTaskRunner = { - val numCores = Runtime.getRuntime().availableProcessors() - val keepAliveTime = 60000L - val workQueue = new LinkedBlockingQueue[Runnable] - val exec = new ThreadPoolExecutor(numCores, - numCores, - keepAliveTime, - TimeUnit.MILLISECONDS, - workQueue, - new ThreadPoolExecutor.CallerRunsPolicy) - JavaConversions.asTaskRunner(exec) - } - -} diff --git a/src/library/scala/concurrent/ThreadPoolRunner.scala b/src/library/scala/concurrent/ThreadPoolRunner.scala index afa14ed2fa..7784681f71 100644 --- a/src/library/scala/concurrent/ThreadPoolRunner.scala +++ b/src/library/scala/concurrent/ThreadPoolRunner.scala @@ -17,7 +17,7 @@ import scala.language.implicitConversions * @author Philipp Haller */ @deprecated("Use `ExecutionContext` instead.", "2.10.0") -trait ThreadPoolRunner extends FutureTaskRunner { +private[scala] trait ThreadPoolRunner extends FutureTaskRunner { type Task[T] = Callable[T] with Runnable type Future[T] = java.util.concurrent.Future[T] diff --git a/src/library/scala/concurrent/ThreadRunner.scala b/src/library/scala/concurrent/ThreadRunner.scala deleted file mode 100644 index cd92db9486..0000000000 --- a/src/library/scala/concurrent/ThreadRunner.scala +++ /dev/null @@ -1,60 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala.concurrent - -import java.lang.Thread -import scala.language.implicitConversions - -/** The `ThreadRunner` trait... - * - * @author Philipp Haller - */ -@deprecated("Use `ExecutionContext` instead.", "2.10.0") -class ThreadRunner extends FutureTaskRunner { - - type Task[T] = () => T - type Future[T] = () => T - - implicit def functionAsTask[S](fun: () => S): Task[S] = fun - implicit def futureAsFunction[S](x: Future[S]): () => S = x - - /* If expression computed successfully return it in `Right`, - * otherwise return exception in `Left`. - */ - private def tryCatch[A](body: => A): Either[Exception, A] = - try Right(body) catch { - case ex: Exception => Left(ex) - } - - def execute[S](task: Task[S]) { - val runnable = new Runnable { - def run() { tryCatch(task()) } - } - (new Thread(runnable)).start() - } - - def submit[S](task: Task[S]): Future[S] = { - val result = new SyncVar[Either[Exception, S]] - val runnable = new Runnable { - def run() { result set tryCatch(task()) } - } - (new Thread(runnable)).start() - () => result.get.fold[S](throw _, identity _) - } - - @deprecated("Use `blocking` instead.", "2.10.0") - def managedBlock(blocker: ManagedBlocker) { - blocker.block() - } - - def shutdown() { - // do nothing - } - -} diff --git a/src/library/scala/concurrent/duration/Duration.scala b/src/library/scala/concurrent/duration/Duration.scala index 0353d61b22..1b50b7fa56 100644 --- a/src/library/scala/concurrent/duration/Duration.scala +++ b/src/library/scala/concurrent/duration/Duration.scala @@ -10,6 +10,7 @@ package scala.concurrent.duration import java.lang.{ Double => JDouble, Long => JLong } import scala.language.implicitConversions +import scala.language.postfixOps object Duration { @@ -103,7 +104,7 @@ object Duration { * Extract length and time unit out of a duration, if it is finite. */ def unapply(d: Duration): Option[(Long, TimeUnit)] = - if (d.isFinite) Some((d.length, d.unit)) else None + if (d.isFinite()) Some((d.length, d.unit)) else None /** * Construct a possibly infinite or undefined Duration from the given number of nanoseconds. @@ -220,6 +221,8 @@ object Duration { final def toMinutes: Long = fail("toMinutes") final def toHours: Long = fail("toHours") final def toDays: Long = fail("toDays") + + final def toCoarsest: Duration = this } /** @@ -519,6 +522,18 @@ sealed abstract class Duration extends Serializable with Ordered[Duration] { * $ovf */ def plus(other: Duration) = this + other + /** + * Return duration which is equal to this duration but with a coarsest Unit, or self in case it is already the coarsest Unit + * <p/> + * Examples: + * {{{ + * Duration(60, MINUTES).toCoarsest // Duration(1, HOURS) + * Duration(1000, MILLISECONDS).toCoarsest // Duration(1, SECONDS) + * Duration(48, HOURS).toCoarsest // Duration(2, DAYS) + * Duration(5, SECONDS).toCoarsest // Duration(5, SECONDS) + * }}} + */ + def toCoarsest: Duration } object FiniteDuration { @@ -623,7 +638,7 @@ final class FiniteDuration(val length: Long, val unit: TimeUnit) extends Duratio // if this is made a constant, then scalac will elide the conditional and always return +0.0, SI-6331 private[this] def minusZero = -0d def /(divisor: Duration): Double = - if (divisor.isFinite) toNanos.toDouble / divisor.toNanos + if (divisor.isFinite()) toNanos.toDouble / divisor.toNanos else if (divisor eq Undefined) Double.NaN else if ((length < 0) ^ (divisor > Zero)) 0d else minusZero @@ -663,8 +678,8 @@ final class FiniteDuration(val length: Long, val unit: TimeUnit) extends Duratio * Long.MinValue is not a legal `length` anyway. */ private def safeMul(_a: Long, _b: Long): Long = { - val a = math.abs(_a) - val b = math.abs(_b) + val a = scala.math.abs(_a) + val b = scala.math.abs(_b) import java.lang.Long.{ numberOfLeadingZeros => leading } if (leading(a) + leading(b) < 64) throw new IllegalArgumentException("multiplication overflow") val product = a * b @@ -690,6 +705,28 @@ final class FiniteDuration(val length: Long, val unit: TimeUnit) extends Duratio final def isFinite() = true + final def toCoarsest: Duration = { + def loop(length: Long, unit: TimeUnit): FiniteDuration = { + def coarserOrThis(coarser: TimeUnit, divider: Int) = + if (length % divider == 0) loop(length / divider, coarser) + else if (unit == this.unit) this + else FiniteDuration(length, unit) + + unit match { + case DAYS => FiniteDuration(length, unit) + case HOURS => coarserOrThis(DAYS, 24) + case MINUTES => coarserOrThis(HOURS, 60) + case SECONDS => coarserOrThis(MINUTES, 60) + case MILLISECONDS => coarserOrThis(SECONDS, 1000) + case MICROSECONDS => coarserOrThis(MILLISECONDS, 1000) + case NANOSECONDS => coarserOrThis(MICROSECONDS, 1000) + } + } + + if (unit == DAYS || length == 0) this + else loop(length, unit) + } + override def equals(other: Any) = other match { case x: FiniteDuration => toNanos == x.toNanos case _ => super.equals(other) diff --git a/src/library/scala/concurrent/duration/package.scala b/src/library/scala/concurrent/duration/package.scala index 2fd735f19e..d166975445 100644 --- a/src/library/scala/concurrent/duration/package.scala +++ b/src/library/scala/concurrent/duration/package.scala @@ -36,19 +36,19 @@ package object duration { final val NANOSECONDS = java.util.concurrent.TimeUnit.NANOSECONDS final val SECONDS = java.util.concurrent.TimeUnit.SECONDS - implicit def pairIntToDuration(p: (Int, TimeUnit)): Duration = Duration(p._1, p._2) + implicit def pairIntToDuration(p: (Int, TimeUnit)): Duration = Duration(p._1.toLong, p._2) implicit def pairLongToDuration(p: (Long, TimeUnit)): FiniteDuration = Duration(p._1, p._2) implicit def durationToPair(d: Duration): (Long, TimeUnit) = (d.length, d.unit) - implicit final class DurationInt(val n: Int) extends AnyVal with DurationConversions { - override protected def durationIn(unit: TimeUnit): FiniteDuration = Duration(n, unit) + implicit final class DurationInt(private val n: Int) extends AnyVal with DurationConversions { + override protected def durationIn(unit: TimeUnit): FiniteDuration = Duration(n.toLong, unit) } - implicit final class DurationLong(val n: Long) extends AnyVal with DurationConversions { + implicit final class DurationLong(private val n: Long) extends AnyVal with DurationConversions { override protected def durationIn(unit: TimeUnit): FiniteDuration = Duration(n, unit) } - implicit final class DurationDouble(val d: Double) extends AnyVal with DurationConversions { + implicit final class DurationDouble(private val d: Double) extends AnyVal with DurationConversions { override protected def durationIn(unit: TimeUnit): FiniteDuration = Duration(d, unit) match { case f: FiniteDuration => f @@ -59,17 +59,17 @@ package object duration { /* * Avoid reflection based invocation by using non-duck type */ - implicit final class IntMult(val i: Int) extends AnyVal { - def *(d: Duration) = d * i - def *(d: FiniteDuration) = d * i + implicit final class IntMult(private val i: Int) extends AnyVal { + def *(d: Duration) = d * i.toDouble + def *(d: FiniteDuration) = d * i.toLong } - implicit final class LongMult(val i: Long) extends AnyVal { - def *(d: Duration) = d * i - def *(d: FiniteDuration) = d * i + implicit final class LongMult(private val i: Long) extends AnyVal { + def *(d: Duration) = d * i.toDouble + def *(d: FiniteDuration) = d * i.toLong } - implicit final class DoubleMult(val f: Double) extends AnyVal { - def *(d: Duration) = d * f + implicit final class DoubleMult(private val f: Double) extends AnyVal { + def *(d: Duration) = d * f.toDouble } } diff --git a/src/library/scala/concurrent/impl/ExecutionContextImpl.scala b/src/library/scala/concurrent/impl/ExecutionContextImpl.scala index 0aa6b37ffc..479720287c 100644 --- a/src/library/scala/concurrent/impl/ExecutionContextImpl.scala +++ b/src/library/scala/concurrent/impl/ExecutionContextImpl.scala @@ -30,7 +30,7 @@ private[scala] class ExecutionContextImpl private[impl] (es: Executor, reporter: } // Implement BlockContext on FJP threads - class DefaultThreadFactory(daemonic: Boolean) extends ThreadFactory with ForkJoinPool.ForkJoinWorkerThreadFactory { + class DefaultThreadFactory(daemonic: Boolean) extends ThreadFactory with ForkJoinPool.ForkJoinWorkerThreadFactory { def wire[T <: Thread](thread: T): T = { thread.setDaemon(daemonic) thread.setUncaughtExceptionHandler(uncaughtExceptionHandler) @@ -57,22 +57,22 @@ private[scala] class ExecutionContextImpl private[impl] (es: Executor, reporter: def createExecutorService: ExecutorService = { - def getInt(name: String, f: String => Int): Int = - try f(System.getProperty(name)) catch { case e: Exception => Runtime.getRuntime.availableProcessors } - def range(floor: Int, desired: Int, ceiling: Int): Int = - if (ceiling < floor) range(ceiling, desired, floor) else scala.math.min(scala.math.max(desired, floor), ceiling) + def getInt(name: String, default: String) = (try System.getProperty(name, default) catch { + case e: SecurityException => default + }) match { + case s if s.charAt(0) == 'x' => (Runtime.getRuntime.availableProcessors * s.substring(1).toDouble).ceil.toInt + case other => other.toInt + } + + def range(floor: Int, desired: Int, ceiling: Int) = scala.math.min(scala.math.max(floor, desired), ceiling) val desiredParallelism = range( - getInt("scala.concurrent.context.minThreads", _.toInt), - getInt("scala.concurrent.context.numThreads", { - case null | "" => Runtime.getRuntime.availableProcessors - case s if s.charAt(0) == 'x' => (Runtime.getRuntime.availableProcessors * s.substring(1).toDouble).ceil.toInt - case other => other.toInt - }), - getInt("scala.concurrent.context.maxThreads", _.toInt)) + getInt("scala.concurrent.context.minThreads", "1"), + getInt("scala.concurrent.context.numThreads", "x1"), + getInt("scala.concurrent.context.maxThreads", "x1")) val threadFactory = new DefaultThreadFactory(daemonic = true) - + try { new ForkJoinPool( desiredParallelism, @@ -96,12 +96,26 @@ private[scala] class ExecutionContextImpl private[impl] (es: Executor, reporter: } } - def execute(runnable: Runnable): Unit = executor match { case fj: ForkJoinPool => - val fjt = runnable match { + val fjt: ForkJoinTask[_] = runnable match { case t: ForkJoinTask[_] => t - case runnable => new ForkJoinTask[Unit] { + case r => new ExecutionContextImpl.AdaptedForkJoinTask(r) + } + Thread.currentThread match { + case fjw: ForkJoinWorkerThread if fjw.getPool eq fj => fjt.fork() + case _ => fj execute fjt + } + case generic => generic execute runnable + } + + def reportFailure(t: Throwable) = reporter(t) +} + + +private[concurrent] object ExecutionContextImpl { + + final class AdaptedForkJoinTask(runnable: Runnable) extends ForkJoinTask[Unit] { final override def setRawResult(u: Unit): Unit = () final override def getRawResult(): Unit = () final override def exec(): Boolean = try { runnable.run(); true } catch { @@ -114,18 +128,7 @@ private[scala] class ExecutionContextImpl private[impl] (es: Executor, reporter: throw anything } } - } - Thread.currentThread match { - case fjw: ForkJoinWorkerThread if fjw.getPool eq fj => fjt.fork() - case _ => fj execute fjt - } - case generic => generic execute runnable - } - - def reportFailure(t: Throwable) = reporter(t) -} -private[concurrent] object ExecutionContextImpl { def fromExecutor(e: Executor, reporter: Throwable => Unit = ExecutionContext.defaultReporter): ExecutionContextImpl = new ExecutionContextImpl(e, reporter) def fromExecutorService(es: ExecutorService, reporter: Throwable => Unit = ExecutionContext.defaultReporter): ExecutionContextImpl with ExecutionContextExecutorService = new ExecutionContextImpl(es, reporter) with ExecutionContextExecutorService { diff --git a/src/library/scala/concurrent/impl/Future.scala b/src/library/scala/concurrent/impl/Future.scala index 89d10e5c47..042d32c234 100644 --- a/src/library/scala/concurrent/impl/Future.scala +++ b/src/library/scala/concurrent/impl/Future.scala @@ -12,7 +12,7 @@ package scala.concurrent.impl import scala.concurrent.ExecutionContext import scala.util.control.NonFatal -import scala.util.{Try, Success, Failure} +import scala.util.{ Success, Failure } private[concurrent] object Future { diff --git a/src/library/scala/concurrent/impl/Promise.scala b/src/library/scala/concurrent/impl/Promise.scala index c9b2a15f2f..b15601058e 100644 --- a/src/library/scala/concurrent/impl/Promise.scala +++ b/src/library/scala/concurrent/impl/Promise.scala @@ -82,11 +82,11 @@ private[concurrent] object Promise { * 2. Complete, with a result. * 3. Linked to another DefaultPromise. * - * If a DefaultPromise is linked it another DefaultPromise then it will + * If a DefaultPromise is linked to another DefaultPromise, it will * delegate all its operations to that other promise. This means that two * DefaultPromises that are linked will appear, to external callers, to have - * exactly the same state and behaviour. E.g. they will both appear to be - * either complete or incomplete, and with the same values. + * exactly the same state and behaviour. For instance, both will appear as + * incomplete, or as complete with the same result value. * * A DefaultPromise stores its state entirely in the AnyRef cell exposed by * AbstractPromise. The type of object stored in the cell fully describes the @@ -155,7 +155,7 @@ private[concurrent] object Promise { /** Get the root promise for this promise, compressing the link chain to that * promise if necessary. - * + * * For promises that are not linked, the result of calling * `compressedRoot()` will the promise itself. However for linked promises, * this method will traverse each link until it locates the root promise at @@ -265,7 +265,7 @@ private[concurrent] object Promise { } def onComplete[U](func: Try[T] => U)(implicit executor: ExecutionContext): Unit = { - val preparedEC = executor.prepare + val preparedEC = executor.prepare() val runnable = new CallbackRunnable[T](preparedEC, func) dispatchOrAddCallback(runnable) } @@ -329,7 +329,7 @@ private[concurrent] object Promise { def onComplete[U](func: Try[T] => U)(implicit executor: ExecutionContext): Unit = { val completedAs = value.get - val preparedEC = executor.prepare + val preparedEC = executor.prepare() (new CallbackRunnable(preparedEC, func)).executeWithValue(completedAs) } diff --git a/src/library/scala/concurrent/ops.scala b/src/library/scala/concurrent/ops.scala deleted file mode 100644 index 4c91e78dc7..0000000000 --- a/src/library/scala/concurrent/ops.scala +++ /dev/null @@ -1,73 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala.concurrent - -import java.lang.Thread -import scala.util.control.Exception.allCatch - -/** The object `ops` ... - * - * @author Martin Odersky, Stepan Koltsov, Philipp Haller - */ -@deprecated("Use `Future` instead.", "2.10.0") -object ops -{ - val defaultRunner: FutureTaskRunner = TaskRunners.threadRunner - - /** - * If expression computed successfully return it in `Right`, - * otherwise return exception in `Left`. - */ - private def tryCatch[A](body: => A): Either[Throwable, A] = - allCatch[A] either body - - private def getOrThrow[T <: Throwable, A](x: Either[T, A]): A = - x.fold[A](throw _, identity _) - - /** Evaluates an expression asynchronously. - * - * @param p the expression to evaluate - */ - def spawn(p: => Unit)(implicit runner: TaskRunner = defaultRunner): Unit = { - runner execute runner.functionAsTask(() => p) - } - - /** Evaluates an expression asynchronously, and returns a closure for - * retrieving the result. - * - * @param p the expression to evaluate - * @return a closure which returns the result once it has been computed - */ - def future[A](p: => A)(implicit runner: FutureTaskRunner = defaultRunner): () => A = { - runner.futureAsFunction(runner submit runner.functionAsTask(() => p)) - } - - /** Evaluates two expressions in parallel. Invoking `par` blocks the current - * thread until both expressions have been evaluated. - * - * @param xp the first expression to evaluate - * @param yp the second expression to evaluate - * - * @return a pair holding the evaluation results - */ - def par[A, B](xp: => A, yp: => B)(implicit runner: TaskRunner = defaultRunner): (A, B) = { - val y = new SyncVar[Either[Throwable, B]] - spawn { y set tryCatch(yp) } - (xp, getOrThrow(y.get)) - } - -/* - def parMap[a,b](f: a => b, xs: Array[a]): Array[b] = { - val results = new Array[b](xs.length); - replicate(0, xs.length) { i => results(i) = f(xs(i)) } - results - } -*/ - -} diff --git a/src/library/scala/concurrent/package.scala b/src/library/scala/concurrent/package.scala index 3e849f1722..cc1350f5a9 100644 --- a/src/library/scala/concurrent/package.scala +++ b/src/library/scala/concurrent/package.scala @@ -19,26 +19,30 @@ package object concurrent { type TimeoutException = java.util.concurrent.TimeoutException /** Starts an asynchronous computation and returns a `Future` object with the result of that computation. - * + * * The result becomes available once the asynchronous computation is completed. - * + * * @tparam T the type of the result * @param body the asynchronous computation - * @param execctx the execution context on which the future is run + * @param executor the execution context on which the future is run * @return the `Future` holding the result of the computation */ - def future[T](body: =>T)(implicit execctx: ExecutionContext): Future[T] = Future[T](body) + @deprecated("Use `Future { ... }` instead.", "2.11.0") + // removal planned for 2.13.0 + def future[T](body: =>T)(implicit @deprecatedName('execctx) executor: ExecutionContext): Future[T] = Future[T](body) /** Creates a promise object which can be completed with a value or an exception. - * + * * @tparam T the type of the value in the promise * @return the newly created `Promise` object */ + @deprecated("Use `Promise[T]()` instead.", "2.11.0") + // removal planned for 2.13.0 def promise[T](): Promise[T] = Promise[T]() /** Used to designate a piece of code which potentially blocks, allowing the current [[BlockContext]] to adjust * the runtime's behavior. - * Properly marking blocking code may improve performance or avoid deadlocks. + * Properly marking blocking code may improve performance or avoid deadlocks. * * Blocking on an [[Awaitable]] should be done using [[Await.result]] instead of `blocking`. * @@ -53,22 +57,22 @@ package object concurrent { package concurrent { @implicitNotFound("Don't call `Awaitable` methods directly, use the `Await` object.") sealed trait CanAwait - + /** * Internal usage only, implementation detail. */ private[concurrent] object AwaitPermission extends CanAwait - + /** * `Await` is what is used to ensure proper handling of blocking for `Awaitable` instances. */ object Await { /** * Await the "completed" state of an `Awaitable`. - * + * * Although this method is blocking, the internal use of [[scala.concurrent.blocking blocking]] ensures that * the underlying [[ExecutionContext]] is prepared to properly manage the blocking. - * + * * @param awaitable * the `Awaitable` to be awaited * @param atMost @@ -84,13 +88,13 @@ package concurrent { @throws(classOf[InterruptedException]) def ready[T](awaitable: Awaitable[T], atMost: Duration): awaitable.type = blocking(awaitable.ready(atMost)(AwaitPermission)) - + /** * Await and return the result (of type `T`) of an `Awaitable`. - * + * * Although this method is blocking, the internal use of [[scala.concurrent.blocking blocking]] ensures that * the underlying [[ExecutionContext]] to properly detect blocking and ensure that there are no deadlocks. - * + * * @param awaitable * the `Awaitable` to be awaited * @param atMost diff --git a/src/library/scala/deprecatedInheritance.scala b/src/library/scala/deprecatedInheritance.scala index 70065560b1..7d20219d4d 100644 --- a/src/library/scala/deprecatedInheritance.scala +++ b/src/library/scala/deprecatedInheritance.scala @@ -11,7 +11,8 @@ package scala /** An annotation that designates that inheriting from a class is deprecated. * * This is usually done to warn about a non-final class being made final in a future version. - * Sub-classing such a class then generates a warning. + * Sub-classing such a class then generates a warning. No warnings are generated if the + * subclass is in the same compilation unit. * * @param message the message to print during compilation if the class was sub-classed * @param since a string identifying the first version in which inheritance was deprecated diff --git a/src/library/scala/io/AnsiColor.scala b/src/library/scala/io/AnsiColor.scala new file mode 100644 index 0000000000..39e2e3b0ca --- /dev/null +++ b/src/library/scala/io/AnsiColor.scala @@ -0,0 +1,53 @@ +package scala +package io + +trait AnsiColor { + /** Foreground color for ANSI black */ + final val BLACK = "\u001b[30m" + /** Foreground color for ANSI red */ + final val RED = "\u001b[31m" + /** Foreground color for ANSI green */ + final val GREEN = "\u001b[32m" + /** Foreground color for ANSI yellow */ + final val YELLOW = "\u001b[33m" + /** Foreground color for ANSI blue */ + final val BLUE = "\u001b[34m" + /** Foreground color for ANSI magenta */ + final val MAGENTA = "\u001b[35m" + /** Foreground color for ANSI cyan */ + final val CYAN = "\u001b[36m" + /** Foreground color for ANSI white */ + final val WHITE = "\u001b[37m" + + /** Background color for ANSI black */ + final val BLACK_B = "\u001b[40m" + /** Background color for ANSI red */ + final val RED_B = "\u001b[41m" + /** Background color for ANSI green */ + final val GREEN_B = "\u001b[42m" + /** Background color for ANSI yellow */ + final val YELLOW_B = "\u001b[43m" + /** Background color for ANSI blue */ + final val BLUE_B = "\u001b[44m" + /** Background color for ANSI magenta */ + final val MAGENTA_B = "\u001b[45m" + /** Background color for ANSI cyan */ + final val CYAN_B = "\u001b[46m" + /** Background color for ANSI white */ + final val WHITE_B = "\u001b[47m" + + /** Reset ANSI styles */ + final val RESET = "\u001b[0m" + /** ANSI bold */ + final val BOLD = "\u001b[1m" + /** ANSI underlines */ + final val UNDERLINED = "\u001b[4m" + /** ANSI blink */ + final val BLINK = "\u001b[5m" + /** ANSI reversed */ + final val REVERSED = "\u001b[7m" + /** ANSI invisible */ + final val INVISIBLE = "\u001b[8m" +} + +object AnsiColor extends AnsiColor { } diff --git a/src/library/scala/io/BufferedSource.scala b/src/library/scala/io/BufferedSource.scala index 767f06fd3f..1c87a1f421 100644 --- a/src/library/scala/io/BufferedSource.scala +++ b/src/library/scala/io/BufferedSource.scala @@ -8,9 +8,11 @@ package scala.io +import java.util.Arrays import java.io.{ InputStream, BufferedReader, InputStreamReader, PushbackReader } import Source.DefaultBufSize import scala.collection.{ Iterator, AbstractIterator } +import scala.collection.mutable.ArrayBuffer /** This object provides convenience methods to create an iterable * representation of a source file. @@ -40,7 +42,7 @@ class BufferedSource(inputStream: InputStream, bufferSize: Int)(implicit val cod map (_.toChar) ) - class BufferedLineIterator extends AbstractIterator[String] with Iterator[String] { + private def decachedReader: BufferedReader = { // Don't want to lose a buffered char sitting in iter either. Yes, // this is ridiculous, but if I can't get rid of Source, and all the // Iterator bits are designed into Source, and people create Sources @@ -48,18 +50,21 @@ class BufferedSource(inputStream: InputStream, bufferSize: Int)(implicit val cod // that calls hasNext to find out if they're empty, and that leads // to chars being buffered, and no, I don't work here, they left a // door unlocked. - private val lineReader: BufferedReader = { - // To avoid inflicting this silliness indiscriminately, we can - // skip it if the char reader was never created: and almost always - // it will not have been created, since getLines will be called - // immediately on the source. - if (charReaderCreated && iter.hasNext) { - val pb = new PushbackReader(charReader) - pb unread iter.next() - new BufferedReader(pb, bufferSize) - } - else charReader + // To avoid inflicting this silliness indiscriminately, we can + // skip it if the char reader was never created: and almost always + // it will not have been created, since getLines will be called + // immediately on the source. + if (charReaderCreated && iter.hasNext) { + val pb = new PushbackReader(charReader) + pb unread iter.next().toInt + new BufferedReader(pb, bufferSize) } + else charReader + } + + + class BufferedLineIterator extends AbstractIterator[String] with Iterator[String] { + private val lineReader = decachedReader var nextLine: String = null override def hasNext = { @@ -73,11 +78,24 @@ class BufferedSource(inputStream: InputStream, bufferSize: Int)(implicit val cod if (nextLine == null) lineReader.readLine else try nextLine finally nextLine = null } - if (result == null) Iterator.empty.next + if (result == null) Iterator.empty.next() else result } } override def getLines(): Iterator[String] = new BufferedLineIterator -} + /** Efficiently converts the entire remaining input into a string. */ + override def mkString = { + // Speed up slurping of whole data set in the simplest cases. + val allReader = decachedReader + val sb = new StringBuilder + val buf = new Array[Char](bufferSize) + var n = 0 + while (n != -1) { + n = charReader.read(buf) + if (n>0) sb.appendAll(buf, 0, n) + } + sb.result + } +} diff --git a/src/library/scala/io/BytePickle.scala b/src/library/scala/io/BytePickle.scala deleted file mode 100644 index 2c4a0bd2da..0000000000 --- a/src/library/scala/io/BytePickle.scala +++ /dev/null @@ -1,318 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala.io - -import scala.collection.mutable - -/** - * Pickler combinators. - * Based on a Haskell library by Andrew Kennedy, - * see <a href="http://research.microsoft.com/~akenn/fun/" - * target="_top">http://research.microsoft.com/~akenn/fun/</a>. - * - * @author Philipp Haller - * @version 1.1 - */ -@deprecated("This class will be removed.", "2.10.0") -object BytePickle { - abstract class SPU[T] { - def appP(a: T, state: PicklerState): PicklerState - def appU(state: UnPicklerState): (T, UnPicklerState) - } - - def pickle[T](p: SPU[T], a: T): Array[Byte] = - p.appP(a, new PicklerState(new Array[Byte](0), new PicklerEnv)).stream - - def unpickle[T](p: SPU[T], stream: Array[Byte]): T = - p.appU(new UnPicklerState(stream, new UnPicklerEnv))._1 - - abstract class PU[T] { - def appP(a: T, state: Array[Byte]): Array[Byte] - def appU(state: Array[Byte]): (T, Array[Byte]) - } - - def upickle[T](p: PU[T], a: T): Array[Byte] = - p.appP(a, new Array[Byte](0)) - - def uunpickle[T](p: PU[T], stream: Array[Byte]): T = - p.appU(stream)._1 - - class PicklerEnv extends mutable.HashMap[Any, Int] { - private var cnt: Int = 64 - def nextLoc() = { cnt += 1; cnt } - } - - class UnPicklerEnv extends mutable.HashMap[Int, Any] { - private var cnt: Int = 64 - def nextLoc() = { cnt += 1; cnt } - } - - class PicklerState(val stream: Array[Byte], val dict: PicklerEnv) - class UnPicklerState(val stream: Array[Byte], val dict: UnPicklerEnv) - - abstract class RefDef - case class Ref() extends RefDef - case class Def() extends RefDef - - def refDef: PU[RefDef] = new PU[RefDef] { - def appP(b: RefDef, s: Array[Byte]): Array[Byte] = - b match { - case Ref() => Array.concat(s, Array[Byte](0)) - case Def() => Array.concat(s, Array[Byte](1)) - }; - def appU(s: Array[Byte]): (RefDef, Array[Byte]) = - if (s(0) == (0: Byte)) (Ref(), s.slice(1, s.length)) - else (Def(), s.slice(1, s.length)); - } - - val REF = 0 - val DEF = 1 - - def unat: PU[Int] = new PU[Int] { - def appP(n: Int, s: Array[Byte]): Array[Byte] = - Array.concat(s, nat2Bytes(n)); - def appU(s: Array[Byte]): (Int, Array[Byte]) = { - var num = 0 - def readNat: Int = { - var b = 0; - var x = 0; - do { - b = s(num) - num += 1 - x = (x << 7) + (b & 0x7f); - } while ((b & 0x80) != 0); - x - } - (readNat, s.slice(num, s.length)) - } - } - - def share[a](pa: SPU[a]): SPU[a] = new SPU[a] { - def appP(v: a, state: PicklerState): PicklerState = { - /* - - is there some value equal to v associated with a location l in the pickle environment? - - yes: write REF-tag to outstream together with l - - no: - write DEF-tag to outstream - record current location l of outstream - --> serialize value - add entry to pickle environment, mapping v onto l - */ - val pe = state.dict - pe.get(v) match { - case None => - val sPrime = refDef.appP(Def(), state.stream) - val l = pe.nextLoc() - - val sPrimePrime = pa.appP(v, new PicklerState(sPrime, pe)) - - pe.update(v, l) - - return sPrimePrime - case Some(l) => - val sPrime = refDef.appP(Ref(), state.stream) - - return new PicklerState(unat.appP(l, sPrime), pe) - } - } - def appU(state: UnPicklerState): (a, UnPicklerState) = { - /* - - first, read tag (i.e. DEF or REF) - - if REF: - read location l - look up resulting value in unpickler environment - - if DEF: - record location l of input stream - --> deserialize value v with argument deserializer - add entry to unpickler environment, mapping l onto v - */ - val upe = state.dict - val res = refDef.appU(state.stream) - res._1 match { - case Def() => - val l = upe.nextLoc - val res2 = pa.appU(new UnPicklerState(res._2, upe)) - upe.update(l, res2._1) - return res2 - case Ref() => - val res2 = unat.appU(res._2) // read location - upe.get(res2._1) match { // lookup value in unpickler env - case None => throw new IllegalArgumentException("invalid unpickler environment") - case Some(v) => return (v.asInstanceOf[a], new UnPicklerState(res2._2, upe)) - } - } - } - } - - def ulift[t](x: t): PU[t] = new PU[t] { - def appP(a: t, state: Array[Byte]): Array[Byte] = - if (x != a) throw new IllegalArgumentException("value to be pickled (" + a + ") != " + x) - else state; - def appU(state: Array[Byte]) = (x, state) - } - - def lift[t](x: t): SPU[t] = new SPU[t] { - def appP(a: t, state: PicklerState): PicklerState = - if (x != a) { /*throw new IllegalArgumentException("value to be pickled (" + a + ") != " + x);*/ state } - else state; - def appU(state: UnPicklerState) = (x, state) - } - - def usequ[t,u](f: u => t, pa: PU[t], k: t => PU[u]): PU[u] = new PU[u] { - def appP(b: u, s: Array[Byte]): Array[Byte] = { - val a = f(b) - val sPrime = pa.appP(a, s) - val pb = k(a) - val sPrimePrime = pb.appP(b, sPrime) - sPrimePrime - } - def appU(s: Array[Byte]): (u, Array[Byte]) = { - val resPa = pa.appU(s) - val a = resPa._1 - val sPrime = resPa._2 - val pb = k(a) - pb.appU(sPrime) - } - } - - def sequ[t,u](f: u => t, pa: SPU[t], k: t => SPU[u]): SPU[u] = new SPU[u] { - def appP(b: u, s: PicklerState): PicklerState = { - val a = f(b) - val sPrime = pa.appP(a, s) - val pb = k(a) - pb.appP(b, sPrime) - } - def appU(s: UnPicklerState): (u, UnPicklerState) = { - val resPa = pa.appU(s) - val a = resPa._1 - val sPrime = resPa._2 - val pb = k(a) - pb.appU(sPrime) - } - } - - def upair[a,b](pa: PU[a], pb: PU[b]): PU[(a,b)] = { - def fst(p: (a,b)): a = p._1 - def snd(p: (a,b)): b = p._2 - usequ(fst, pa, (x: a) => usequ(snd, pb, (y: b) => ulift((x, y)))) - } - - def pair[a,b](pa: SPU[a], pb: SPU[b]): SPU[(a,b)] = { - def fst(p: (a,b)): a = p._1 - def snd(p: (a,b)): b = p._2 - sequ(fst, pa, (x: a) => sequ(snd, pb, (y: b) => lift((x, y)))) - } - - def triple[a,b,c](pa: SPU[a], pb: SPU[b], pc: SPU[c]): SPU[(a,b,c)] = { - def fst(p: (a,b,c)): a = p._1 - def snd(p: (a,b,c)): b = p._2 - def trd(p: (a,b,c)): c = p._3 - - sequ(fst, pa, - (x: a) => sequ(snd, pb, - (y: b) => sequ(trd, pc, - (z: c) => lift((x, y, z))))) - } - - def uwrap[a,b](i: a => b, j: b => a, pa: PU[a]): PU[b] = - usequ(j, pa, (x: a) => ulift(i(x))) - - def wrap[a,b](i: a => b, j: b => a, pa: SPU[a]): SPU[b] = - sequ(j, pa, (x: a) => lift(i(x))) - - def appendByte(a: Array[Byte], b: Int): Array[Byte] = - Array.concat(a, Array(b.toByte)) - - def nat2Bytes(x: Int): Array[Byte] = { - val buf = new mutable.ArrayBuffer[Byte] - def writeNatPrefix(x: Int) { - val y = x >>> 7; - if (y != 0) writeNatPrefix(y); - buf += ((x & 0x7f) | 0x80).asInstanceOf[Byte]; - } - val y = x >>> 7; - if (y != 0) writeNatPrefix(y); - buf += (x & 0x7f).asInstanceOf[Byte]; - buf.toArray - } - - def nat: SPU[Int] = new SPU[Int] { - def appP(n: Int, s: PicklerState): PicklerState = { - new PicklerState(Array.concat(s.stream, nat2Bytes(n)), s.dict); - } - def appU(s: UnPicklerState): (Int,UnPicklerState) = { - var num = 0 - def readNat: Int = { - var b = 0 - var x = 0 - do { - b = s.stream(num) - num += 1 - x = (x << 7) + (b & 0x7f); - } while ((b & 0x80) != 0); - x - } - (readNat, new UnPicklerState(s.stream.slice(num, s.stream.length), s.dict)) - } - } - - def byte: SPU[Byte] = new SPU[Byte] { - def appP(b: Byte, s: PicklerState): PicklerState = - new PicklerState(Array.concat(s.stream, Array(b)), s.dict) - def appU(s: UnPicklerState): (Byte, UnPicklerState) = - (s.stream(0), new UnPicklerState(s.stream.slice(1, s.stream.length), s.dict)); - } - - def string: SPU[String] = share(wrap( - (a: Array[Byte]) => (Codec fromUTF8 a).mkString, - (s: String) => Codec toUTF8 s, - bytearray - )) - - def bytearray: SPU[Array[Byte]] = { - wrap((l:List[Byte]) => l.toArray, (_.toList), list(byte)) - } - - def bool: SPU[Boolean] = { - def toEnum(b: Boolean) = if (b) 1 else 0 - def fromEnum(n: Int) = if (n == 0) false else true - wrap(fromEnum, toEnum, nat) - } - - def ufixedList[A](pa: PU[A])(n: Int): PU[List[A]] = { - def pairToList(p: (A, List[A])): List[A] = - p._1 :: p._2; - def listToPair(l: List[A]): (A, List[A]) = - (l: @unchecked) match { case x :: xs => (x, xs) } - - if (n == 0) ulift(Nil) - else - uwrap(pairToList, listToPair, upair(pa, ufixedList(pa)(n-1))) - } - - def fixedList[a](pa: SPU[a])(n: Int): SPU[List[a]] = { - def pairToList(p: (a,List[a])): List[a] = - p._1 :: p._2; - def listToPair(l: List[a]): (a,List[a]) = - (l: @unchecked) match { case x :: xs => (x, xs) } - - if (n == 0) lift(Nil) - else - wrap(pairToList, listToPair, pair(pa, fixedList(pa)(n-1))) - } - - def list[a](pa: SPU[a]): SPU[List[a]] = - sequ((l: List[a])=>l.length, nat, fixedList(pa)); - - def ulist[a](pa: PU[a]): PU[List[a]] = - usequ((l:List[a]) => l.length, unat, ufixedList(pa)); - - def data[a](tag: a => Int, ps: List[()=>SPU[a]]): SPU[a] = - sequ(tag, nat, (x: Int)=> ps.apply(x)()); -} diff --git a/src/library/scala/io/Codec.scala b/src/library/scala/io/Codec.scala index 5d046e48b0..60f99199cb 100644 --- a/src/library/scala/io/Codec.scala +++ b/src/library/scala/io/Codec.scala @@ -6,8 +6,8 @@ ** |/ ** \* */ - -package scala.io +package scala +package io import java.nio.charset.{ Charset, CharsetDecoder, CharsetEncoder, CharacterCodingException, CodingErrorAction => Action } import scala.annotation.migration @@ -43,42 +43,37 @@ class Codec(val charSet: Charset) { override def toString = name // these methods can be chained to configure the variables above - def onMalformedInput(newAction: Action): this.type = { _onMalformedInput = newAction ; this } - def onUnmappableCharacter(newAction: Action): this.type = { _onUnmappableCharacter = newAction ; this } - def decodingReplaceWith(newReplacement: String): this.type = { _decodingReplacement = newReplacement ; this } + def onMalformedInput(newAction: Action): this.type = { _onMalformedInput = newAction ; this } + def onUnmappableCharacter(newAction: Action): this.type = { _onUnmappableCharacter = newAction ; this } + def decodingReplaceWith(newReplacement: String): this.type = { _decodingReplacement = newReplacement ; this } def encodingReplaceWith(newReplacement: Array[Byte]): this.type = { _encodingReplacement = newReplacement ; this } - def onCodingException(handler: Handler): this.type = { _onCodingException = handler ; this } + def onCodingException(handler: Handler): this.type = { _onCodingException = handler ; this } def name = charSet.name - def encoder = - applyFunctions[CharsetEncoder](charSet.newEncoder(), - (_ onMalformedInput _onMalformedInput, _onMalformedInput != null), - (_ onUnmappableCharacter _onUnmappableCharacter, _onUnmappableCharacter != null), - (_ replaceWith _encodingReplacement, _encodingReplacement != null) - ) - - def decoder = - applyFunctions[CharsetDecoder](charSet.newDecoder(), - (_ onMalformedInput _onMalformedInput, _onMalformedInput != null), - (_ onUnmappableCharacter _onUnmappableCharacter, _onUnmappableCharacter != null), - (_ replaceWith _decodingReplacement, _decodingReplacement != null) - ) + def encoder: CharsetEncoder = { + val enc = charSet.newEncoder() + if (_onMalformedInput ne null) enc onMalformedInput _onMalformedInput + if (_onUnmappableCharacter ne null) enc onUnmappableCharacter _onUnmappableCharacter + if (_encodingReplacement ne null) enc replaceWith _encodingReplacement + enc + } + def decoder: CharsetDecoder = { + val dec = charSet.newDecoder() + if (_onMalformedInput ne null) dec onMalformedInput _onMalformedInput + if (_onUnmappableCharacter ne null) dec onUnmappableCharacter _onUnmappableCharacter + if (_decodingReplacement ne null) dec replaceWith _decodingReplacement + dec + } def wrap(body: => Int): Int = try body catch { case e: CharacterCodingException => _onCodingException(e) } - - // call a series of side effecting methods on an object, finally returning the object - private def applyFunctions[T](x: T, fs: Configure[T]*) = - fs.foldLeft(x)((x, pair) => pair match { - case (f, cond) => if (cond) f(x) else x - }) } trait LowPriorityCodecImplicits { self: Codec.type => /** The Codec of Last Resort. */ - implicit def fallbackSystemCodec: Codec = defaultCharsetCodec + implicit lazy val fallbackSystemCodec: Codec = defaultCharsetCodec } object Codec extends LowPriorityCodecImplicits { @@ -90,9 +85,9 @@ object Codec extends LowPriorityCodecImplicits { * the fact that you can influence anything at all via -Dfile.encoding * as an accident, with any anomalies considered "not a bug". */ - def defaultCharsetCodec = apply(Charset.defaultCharset) - def fileEncodingCodec = apply(scala.util.Properties.encodingString) - def default = defaultCharsetCodec + def defaultCharsetCodec = apply(Charset.defaultCharset) + def fileEncodingCodec = apply(scala.util.Properties.encodingString) + def default = defaultCharsetCodec def apply(encoding: String): Codec = new Codec(Charset forName encoding) def apply(charSet: Charset): Codec = new Codec(charSet) @@ -130,7 +125,7 @@ object Codec extends LowPriorityCodecImplicits { bytes } - implicit def string2codec(s: String) = apply(s) - implicit def charset2codec(c: Charset) = apply(c) - implicit def decoder2codec(cd: CharsetDecoder) = apply(cd) + implicit def string2codec(s: String): Codec = apply(s) + implicit def charset2codec(c: Charset): Codec = apply(c) + implicit def decoder2codec(cd: CharsetDecoder): Codec = apply(cd) } diff --git a/src/library/scala/io/Position.scala b/src/library/scala/io/Position.scala index daa4e103be..011d0f17af 100644 --- a/src/library/scala/io/Position.scala +++ b/src/library/scala/io/Position.scala @@ -6,7 +6,8 @@ ** |/ ** \* */ -package scala.io +package scala +package io /** The object Position provides convenience methods to encode * line and column number in one single integer. The encoded line @@ -33,7 +34,7 @@ package scala.io * @author Burak Emir (translated from work by Matthias Zenger and others) */ @deprecated("This class will be removed.", "2.10.0") -abstract class Position { +private[scala] abstract class Position { /** Definable behavior for overflow conditions. */ def checkInput(line: Int, column: Int): Unit @@ -67,15 +68,7 @@ abstract class Position { def toString(pos: Int): String = line(pos) + ":" + column(pos) } -object Position extends Position { - /** The undefined position */ - @deprecated("This will be removed", "2.9.0") - final val NOPOS = 0 - - /** The first position in a source file */ - @deprecated("This will be removed", "2.9.0") - final val FIRSTPOS = encode(1, 1) - +private[scala] object Position extends Position { def checkInput(line: Int, column: Int) { if (line < 0) throw new IllegalArgumentException(line + " < 0") diff --git a/src/library/scala/io/Source.scala b/src/library/scala/io/Source.scala index b13729aefe..74c3e06839 100644 --- a/src/library/scala/io/Source.scala +++ b/src/library/scala/io/Source.scala @@ -6,7 +6,8 @@ ** |/ ** \* */ -package scala.io +package scala +package io import scala.collection.AbstractIterator import java.io.{ FileInputStream, InputStream, PrintStream, File => JFile } @@ -194,11 +195,11 @@ abstract class Source extends Iterator[Char] { lazy val iter: BufferedIterator[Char] = Source.this.iter.buffered def isNewline(ch: Char) = ch == '\r' || ch == '\n' def getc() = iter.hasNext && { - val ch = iter.next + val ch = iter.next() if (ch == '\n') false else if (ch == '\r') { if (iter.hasNext && iter.head == '\n') - iter.next + iter.next() false } @@ -209,7 +210,7 @@ abstract class Source extends Iterator[Char] { } def hasNext = iter.hasNext def next = { - sb.clear + sb.clear() while (getc()) { } sb.toString } @@ -227,7 +228,7 @@ abstract class Source extends Iterator[Char] { /** Returns next character. */ - def next(): Char = positioner.next + def next(): Char = positioner.next() class Positioner(encoder: Position) { def this() = this(RelaxedPosition) @@ -245,7 +246,7 @@ abstract class Source extends Iterator[Char] { var tabinc = 4 def next(): Char = { - ch = iter.next + ch = iter.next() pos = encoder.encode(cline, ccol) ch match { case '\n' => @@ -267,7 +268,7 @@ abstract class Source extends Iterator[Char] { } object RelaxedPositioner extends Positioner(RelaxedPosition) { } object NoPositioner extends Positioner(Position) { - override def next(): Char = iter.next + override def next(): Char = iter.next() } def ch = positioner.ch def pos = positioner.pos diff --git a/src/library/scala/io/StdIn.scala b/src/library/scala/io/StdIn.scala new file mode 100644 index 0000000000..64836ecd6e --- /dev/null +++ b/src/library/scala/io/StdIn.scala @@ -0,0 +1,229 @@ +package scala +package io + +import java.text.MessageFormat + +/** private[scala] because this is not functionality we should be providing + * in the standard library, at least not in this idiosyncractic form. + * Factored into trait because it is better code structure regardless. + */ +private[scala] trait StdIn { + import scala.Console._ + + /** Read a full line from the default input. Returns `null` if the end of the + * input stream has been reached. + * + * @return the string read from the terminal or null if the end of stream was reached. + */ + def readLine(): String = in.readLine() + + /** Print and flush formatted text to the default output, and read a full line from the default input. + * Returns `null` if the end of the input stream has been reached. + * + * @param text the format of the text to print out, as in `printf`. + * @param args the parameters used to instantiate the format, as in `printf`. + * @return the string read from the default input + */ + def readLine(text: String, args: Any*): String = { + printf(text, args: _*) + out.flush() + readLine() + } + + /** Reads a boolean value from an entire line of the default input. + * Has a fairly liberal interpretation of the input. + * + * @return the boolean value read, or false if it couldn't be converted to a boolean + * @throws java.io.EOFException if the end of the input stream has been reached. + */ + def readBoolean(): Boolean = { + val s = readLine() + if (s == null) + throw new java.io.EOFException("Console has reached end of input") + else + s.toLowerCase() match { + case "true" => true + case "t" => true + case "yes" => true + case "y" => true + case _ => false + } + } + + /** Reads a byte value from an entire line of the default input. + * + * @return the Byte that was read + * @throws java.io.EOFException if the end of the + * input stream has been reached. + * @throws java.lang.NumberFormatException if the value couldn't be converted to a Byte + */ + def readByte(): Byte = { + val s = readLine() + if (s == null) + throw new java.io.EOFException("Console has reached end of input") + else + s.toByte + } + + /** Reads a short value from an entire line of the default input. + * + * @return the short that was read + * @throws java.io.EOFException if the end of the + * input stream has been reached. + * @throws java.lang.NumberFormatException if the value couldn't be converted to a Short + */ + def readShort(): Short = { + val s = readLine() + if (s == null) + throw new java.io.EOFException("Console has reached end of input") + else + s.toShort + } + + /** Reads a char value from an entire line of the default input. + * + * @return the Char that was read + * @throws java.io.EOFException if the end of the + * input stream has been reached. + * @throws java.lang.StringIndexOutOfBoundsException if the line read from default input was empty + */ + def readChar(): Char = { + val s = readLine() + if (s == null) + throw new java.io.EOFException("Console has reached end of input") + else + s charAt 0 + } + + /** Reads an int value from an entire line of the default input. + * + * @return the Int that was read + * @throws java.io.EOFException if the end of the + * input stream has been reached. + * @throws java.lang.NumberFormatException if the value couldn't be converted to an Int + */ + def readInt(): Int = { + val s = readLine() + if (s == null) + throw new java.io.EOFException("Console has reached end of input") + else + s.toInt + } + + /** Reads an long value from an entire line of the default input. + * + * @return the Long that was read + * @throws java.io.EOFException if the end of the + * input stream has been reached. + * @throws java.lang.NumberFormatException if the value couldn't be converted to a Long + */ + def readLong(): Long = { + val s = readLine() + if (s == null) + throw new java.io.EOFException("Console has reached end of input") + else + s.toLong + } + + /** Reads a float value from an entire line of the default input. + * @return the Float that was read. + * @throws java.io.EOFException if the end of the + * input stream has been reached. + * @throws java.lang.NumberFormatException if the value couldn't be converted to a Float + * + */ + def readFloat(): Float = { + val s = readLine() + if (s == null) + throw new java.io.EOFException("Console has reached end of input") + else + s.toFloat + } + + /** Reads a double value from an entire line of the default input. + * + * @return the Double that was read. + * @throws java.io.EOFException if the end of the + * input stream has been reached. + * @throws java.lang.NumberFormatException if the value couldn't be converted to a Float + */ + def readDouble(): Double = { + val s = readLine() + if (s == null) + throw new java.io.EOFException("Console has reached end of input") + else + s.toDouble + } + + /** Reads in some structured input (from the default input), specified by + * a format specifier. See class `java.text.MessageFormat` for details of + * the format specification. + * + * @param format the format of the input. + * @return a list of all extracted values. + * @throws java.io.EOFException if the end of the input stream has been + * reached. + */ + def readf(format: String): List[Any] = { + val s = readLine() + if (s == null) + throw new java.io.EOFException("Console has reached end of input") + else + textComponents(new MessageFormat(format).parse(s)) + } + + /** Reads in some structured input (from the default input), specified by + * a format specifier, returning only the first value extracted, according + * to the format specification. + * + * @param format format string, as accepted by `readf`. + * @return The first value that was extracted from the input + */ + def readf1(format: String): Any = readf(format).head + + /** Reads in some structured input (from the default input), specified + * by a format specifier, returning only the first two values extracted, + * according to the format specification. + * + * @param format format string, as accepted by `readf`. + * @return A [[scala.Tuple2]] containing the first two values extracted + */ + def readf2(format: String): (Any, Any) = { + val res = readf(format) + (res.head, res.tail.head) + } + + /** Reads in some structured input (from the default input), specified + * by a format specifier, returning only the first three values extracted, + * according to the format specification. + * + * @param format format string, as accepted by `readf`. + * @return A [[scala.Tuple3]] containing the first three values extracted + */ + def readf3(format: String): (Any, Any, Any) = { + val res = readf(format) + (res.head, res.tail.head, res.tail.tail.head) + } + + private def textComponents(a: Array[AnyRef]): List[Any] = { + var i: Int = a.length - 1 + var res: List[Any] = Nil + while (i >= 0) { + res = (a(i) match { + case x: java.lang.Boolean => x.booleanValue() + case x: java.lang.Byte => x.byteValue() + case x: java.lang.Short => x.shortValue() + case x: java.lang.Character => x.charValue() + case x: java.lang.Integer => x.intValue() + case x: java.lang.Long => x.longValue() + case x: java.lang.Float => x.floatValue() + case x: java.lang.Double => x.doubleValue() + case x => x + }) :: res + i -= 1 + } + res + } +} + +object StdIn extends StdIn diff --git a/src/library/scala/io/UTF8Codec.scala b/src/library/scala/io/UTF8Codec.scala deleted file mode 100644 index e4c2145153..0000000000 --- a/src/library/scala/io/UTF8Codec.scala +++ /dev/null @@ -1,32 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - -package scala.io - -/** - * @author Martin Odersky - * @version 1.0, 04/10/2004 - */ -@deprecated("This class will be removed.", "2.10.0") -object UTF8Codec { - final val UNI_REPLACEMENT_CHAR: Int = 0x0000FFFD - final val UNI_REPLACEMENT_BYTES = Array[Byte](-17, -65, -67) - - // Note, from http://unicode.org/faq/utf_bom.html#utf8-5 - // - // A different issue arises if an unpaired surrogate is encountered when converting - // ill-formed UTF-16 data. By represented such an unpaired surrogate on its own as a - // 3-byte sequence, the resulting UTF-8 data stream would become ill-formed. - // While it faithfully reflects the nature of the input, Unicode conformance - // requires that encoding form conversion always results in valid data stream. - // Therefore a converter must treat this as an error. - // - // Some useful locations: - // http://www.cl.cam.ac.uk/~mgk25/ucs/examples/UTF-8-test.txt -} diff --git a/src/library/scala/math/BigDecimal.scala b/src/library/scala/math/BigDecimal.scala index 62528e15fa..bcbed645a7 100644 --- a/src/library/scala/math/BigDecimal.scala +++ b/src/library/scala/math/BigDecimal.scala @@ -7,7 +7,8 @@ \* */ -package scala.math +package scala +package math import java.{ lang => jl } import java.math.{ MathContext, BigDecimal => BigDec } @@ -15,41 +16,165 @@ import scala.collection.immutable.NumericRange import scala.language.implicitConversions -/** +/** * @author Stephane Micheloud - * @version 1.0 + * @author Rex Kerr + * @version 1.1 * @since 2.7 */ object BigDecimal { + private final val maximumHashScale = 4934 // Quit maintaining hash identity with BigInt beyond this scale + private final val hashCodeNotComputed = 0x5D50690F // Magic value (happens to be "BigDecimal" old MurmurHash3 value) + private final val deci2binary = 3.3219280948873626 // Ratio of log(10) to log(2) private val minCached = -512 private val maxCached = 512 val defaultMathContext = MathContext.DECIMAL128 - @deprecated("Use Long.MinValue", "2.9.0") - val MinLong = new BigDecimal(BigDec valueOf Long.MinValue, defaultMathContext) - - @deprecated("Use Long.MaxValue", "2.9.0") - val MaxLong = new BigDecimal(BigDec valueOf Long.MaxValue, defaultMathContext) - - /** Cache ony for defaultMathContext using BigDecimals in a small range. */ + /** Cache only for defaultMathContext using BigDecimals in a small range. */ private lazy val cache = new Array[BigDecimal](maxCached - minCached + 1) object RoundingMode extends Enumeration { + // Annoying boilerplate to ensure consistency with java.math.RoundingMode + import java.math.{RoundingMode => RM} type RoundingMode = Value - // These are supposed to be the same as java.math.RoundingMode.values, - // though it seems unwise to rely on the correspondence. - val UP, DOWN, CEILING, FLOOR, HALF_UP, HALF_DOWN, HALF_EVEN, UNNECESSARY = Value + val UP = Value(RM.UP.ordinal) + val DOWN = Value(RM.DOWN.ordinal) + val CEILING = Value(RM.CEILING.ordinal) + val FLOOR = Value(RM.FLOOR.ordinal) + val HALF_UP = Value(RM.HALF_UP.ordinal) + val HALF_DOWN = Value(RM.HALF_DOWN.ordinal) + val HALF_EVEN = Value(RM.HALF_EVEN.ordinal) + val UNNECESSARY = Value(RM.UNNECESSARY.ordinal) } + + /** Constructs a `BigDecimal` using the decimal text representation of `Double` value `d`, rounding if necessary. */ + def decimal(d: Double, mc: MathContext): BigDecimal = + new BigDecimal(new BigDec(java.lang.Double.toString(d), mc)) + + /** Constructs a `BigDecimal` using the decimal text representation of `Double` value `d`. */ + def decimal(d: Double): BigDecimal = decimal(d, defaultMathContext) + + /** Constructs a `BigDecimal` using the decimal text representation of `Float` value `f`, rounding if necessary. + * Note that `BigDecimal.decimal(0.1f) != 0.1f` since equality agrees with the `Double` representation, and + * `0.1 != 0.1f`. + */ + def decimal(f: Float, mc: MathContext): BigDecimal = + new BigDecimal(new BigDec(java.lang.Float.toString(f), mc)) + + /** Constructs a `BigDecimal` using the decimal text representation of `Float` value `f`. + * Note that `BigDecimal.decimal(0.1f) != 0.1f` since equality agrees with the `Double` representation, and + * `0.1 != 0.1f`. + */ + def decimal(f: Float): BigDecimal = decimal(f, defaultMathContext) + + // This exists solely to avoid conversion from Int/Long to Float, screwing everything up. + /** Constructs a `BigDecimal` from a `Long`, rounding if necessary. This is identical to `BigDecimal(l, mc)`. */ + def decimal(l: Long, mc: MathContext): BigDecimal = apply(l, mc) + + // This exists solely to avoid conversion from Int/Long to Float, screwing everything up. + /** Constructs a `BigDecimal` from a `Long`. This is identical to `BigDecimal(l)`. */ + def decimal(l: Long): BigDecimal = apply(l) + + /** Constructs a `BigDecimal` using a `java.math.BigDecimal`, rounding if necessary. */ + def decimal(bd: BigDec, mc: MathContext): BigDecimal = new BigDecimal(bd.round(mc), mc) + + /** Constructs a `BigDecimal` by expanding the binary fraction + * contained by `Double` value `d` into a decimal representation, + * rounding if necessary. When a `Float` is converted to a + * `Double`, the binary fraction is preserved, so this method + * also works for converted `Float`s. + */ + def binary(d: Double, mc: MathContext): BigDecimal = new BigDecimal(new BigDec(d, mc), mc) + + /** Constructs a `BigDecimal` by expanding the binary fraction + * contained by `Double` value `d` into a decimal representation. + * Note: this also works correctly on converted `Float`s. + */ + def binary(d: Double): BigDecimal = binary(d, defaultMathContext) + + /** Constructs a `BigDecimal` from a `java.math.BigDecimal`. The + * precision is the default for `BigDecimal` or enough to represent + * the `java.math.BigDecimal` exactly, whichever is greater. + */ + def exact(repr: BigDec): BigDecimal = { + val mc = + if (repr.precision <= defaultMathContext.getPrecision) defaultMathContext + else new MathContext(repr.precision, java.math.RoundingMode.HALF_EVEN) + new BigDecimal(repr, mc) + } + + /** Constructs a `BigDecimal` by fully expanding the binary fraction + * contained by `Double` value `d`, adjusting the precision as + * necessary. Note: this works correctly on converted `Float`s also. + */ + def exact(d: Double): BigDecimal = exact(new BigDec(d)) + + /** Constructs a `BigDecimal` that exactly represents a `BigInt`. + */ + def exact(bi: BigInt): BigDecimal = exact(new BigDec(bi.bigInteger)) + + /** Constructs a `BigDecimal` that exactly represents a `Long`. Note that + * all creation methods for `BigDecimal` that do not take a `MathContext` + * represent a `Long`; this is equivalent to `apply`, `valueOf`, etc.. + */ + def exact(l: Long): BigDecimal = apply(l) + + /** Constructs a `BigDecimal` that exactly represents the number + * specified in a `String`. + */ + def exact(s: String): BigDecimal = exact(new BigDec(s)) + + /** Constructs a 'BigDecimal` that exactly represents the number + * specified in base 10 in a character array. + */ + def exact(cs: Array[Char]): BigDecimal = exact(new BigDec(cs)) + /** Constructs a `BigDecimal` using the java BigDecimal static - * valueOf constructor. + * valueOf constructor. Equivalent to `BigDecimal.decimal`. * * @param d the specified double value * @return the constructed `BigDecimal` */ def valueOf(d: Double): BigDecimal = apply(BigDec valueOf d) + + /** Constructs a `BigDecimal` using the java BigDecimal static + * valueOf constructor, specifying a `MathContext` that is + * used for computations but isn't used for rounding. Use + * `BigDecimal.decimal` to use `MathContext` for rounding, + * or `BigDecimal(java.math.BigDecimal.valueOf(d), mc)` for + * no rounding. + * + * @param d the specified double value + * @param mc the `MathContext` used for future computations + * @return the constructed `BigDecimal` + */ + @deprecated("MathContext is not applied to Doubles in valueOf. Use BigDecimal.decimal to use rounding, or java.math.BigDecimal.valueOf to avoid it.","2.11") def valueOf(d: Double, mc: MathContext): BigDecimal = apply(BigDec valueOf d, mc) + + /** Constructs a `BigDecimal` using the java BigDecimal static + * valueOf constructor. + * + * @param x the specified `Long` value + * @return the constructed `BigDecimal` + */ + def valueOf(x: Long): BigDecimal = apply(x) + + /** Constructs a `BigDecimal` using the java BigDecimal static + * valueOf constructor. This is unlikely to do what you want; + * use `valueOf(f.toDouble)` or `decimal(f)` instead. + */ + @deprecated("Float arguments to valueOf may not do what you wish. Use decimal or valueOf(f.toDouble).","2.11") + def valueOf(f: Float): BigDecimal = valueOf(f.toDouble) + + /** Constructs a `BigDecimal` using the java BigDecimal static + * valueOf constructor. This is unlikely to do what you want; + * use `valueOf(f.toDouble)` or `decimal(f)` instead. + */ + @deprecated("Float arguments to valueOf may not do what you wish. Use decimal or valueOf(f.toDouble).","2.11") + def valueOf(f: Float, mc: MathContext): BigDecimal = valueOf(f.toDouble, mc) + /** Constructs a `BigDecimal` whose value is equal to that of the * specified `Integer` value. * @@ -57,14 +182,22 @@ object BigDecimal { * @return the constructed `BigDecimal` */ def apply(i: Int): BigDecimal = apply(i, defaultMathContext) + + /** Constructs a `BigDecimal` whose value is equal to that of the + * specified `Integer` value, rounding if necessary. + * + * @param i the specified integer value + * @param mc the precision and rounding mode for creation of this value and future operations on it + * @return the constructed `BigDecimal` + */ def apply(i: Int, mc: MathContext): BigDecimal = if (mc == defaultMathContext && minCached <= i && i <= maxCached) { val offset = i - minCached var n = cache(offset) - if (n eq null) { n = new BigDecimal(BigDec.valueOf(i), mc); cache(offset) = n } + if (n eq null) { n = new BigDecimal(BigDec.valueOf(i.toLong), mc); cache(offset) = n } n } - else new BigDecimal(BigDec.valueOf(i), mc) + else apply(i.toLong, mc) /** Constructs a `BigDecimal` whose value is equal to that of the * specified long value. @@ -76,6 +209,13 @@ object BigDecimal { if (minCached <= l && l <= maxCached) apply(l.toInt) else new BigDecimal(BigDec.valueOf(l), defaultMathContext) + /** Constructs a `BigDecimal` whose value is equal to that of the + * specified long value, but rounded if necessary. + * + * @param l the specified long value + * @param mc the precision and rounding mode for creation of this value and future operations on it + * @return the constructed `BigDecimal` + */ def apply(l: Long, mc: MathContext): BigDecimal = new BigDecimal(new BigDec(l, mc), mc) @@ -89,32 +229,62 @@ object BigDecimal { def apply(unscaledVal: Long, scale: Int): BigDecimal = apply(BigInt(unscaledVal), scale) + /** Constructs a `BigDecimal` whose unscaled value is equal to that + * of the specified long value, but rounded if necessary. + * + * @param unscaledVal the value + * @param scale the scale + * @param mc the precision and rounding mode for creation of this value and future operations on it + * @return the constructed `BigDecimal` + */ def apply(unscaledVal: Long, scale: Int, mc: MathContext): BigDecimal = apply(BigInt(unscaledVal), scale, mc) /** Constructs a `BigDecimal` whose value is equal to that of the - * specified double value. + * specified double value. Equivalent to `BigDecimal.decimal`. * * @param d the specified `Double` value * @return the constructed `BigDecimal` */ - def apply(d: Double): BigDecimal = apply(d, defaultMathContext) + def apply(d: Double): BigDecimal = decimal(d, defaultMathContext) + // note we don't use the static valueOf because it doesn't let us supply // a MathContext, but we should be duplicating its logic, modulo caching. - def apply(d: Double, mc: MathContext): BigDecimal = - new BigDecimal(new BigDec(jl.Double.toString(d), mc), mc) + /** Constructs a `BigDecimal` whose value is equal to that of the + * specified double value, but rounded if necessary. Equivalent to + * `BigDecimal.decimal`. + * + * @param d the specified `Double` value + * @param mc the precision and rounding mode for creation of this value and future operations on it + * @return the constructed `BigDecimal` + */ + def apply(d: Double, mc: MathContext): BigDecimal = decimal(d, mc) + + @deprecated("The default conversion from Float may not do what you want. Use BigDecimal.decimal for a String representation, or explicitly convert the Float with .toDouble.", "2.11") + def apply(x: Float): BigDecimal = apply(x.toDouble) + + @deprecated("The default conversion from Float may not do what you want. Use BigDecimal.decimal for a String representation, or explicitly convert the Float with .toDouble.", "2.11") + def apply(x: Float, mc: MathContext): BigDecimal = apply(x.toDouble, mc) /** Translates a character array representation of a `BigDecimal` * into a `BigDecimal`. */ - def apply(x: Array[Char]): BigDecimal = apply(x, defaultMathContext) + def apply(x: Array[Char]): BigDecimal = exact(x) + + /** Translates a character array representation of a `BigDecimal` + * into a `BigDecimal`, rounding if necessary. + */ def apply(x: Array[Char], mc: MathContext): BigDecimal = - new BigDecimal(new BigDec(x.mkString, mc), mc) + new BigDecimal(new BigDec(x, mc), mc) /** Translates the decimal String representation of a `BigDecimal` * into a `BigDecimal`. */ - def apply(x: String): BigDecimal = apply(x, defaultMathContext) + def apply(x: String): BigDecimal = exact(x) + + /** Translates the decimal String representation of a `BigDecimal` + * into a `BigDecimal`, rounding if necessary. + */ def apply(x: String, mc: MathContext): BigDecimal = new BigDecimal(new BigDec(x, mc), mc) @@ -124,7 +294,15 @@ object BigDecimal { * @param x the specified `BigInt` value * @return the constructed `BigDecimal` */ - def apply(x: BigInt): BigDecimal = apply(x, defaultMathContext) + def apply(x: BigInt): BigDecimal = exact(x) + + /** Constructs a `BigDecimal` whose value is equal to that of the + * specified `BigInt` value, rounding if necessary. + * + * @param x the specified `BigInt` value + * @param mc the precision and rounding mode for creation of this value and future operations on it + * @return the constructed `BigDecimal` + */ def apply(x: BigInt, mc: MathContext): BigDecimal = new BigDecimal(new BigDec(x.bigInteger, mc), mc) @@ -135,11 +313,24 @@ object BigDecimal { * @param scale the scale * @return the constructed `BigDecimal` */ - def apply(unscaledVal: BigInt, scale: Int): BigDecimal = apply(unscaledVal, scale, defaultMathContext) + def apply(unscaledVal: BigInt, scale: Int): BigDecimal = + exact(new BigDec(unscaledVal.bigInteger, scale)) + + /** Constructs a `BigDecimal` whose unscaled value is equal to that + * of the specified `BigInt` value. + * + * @param unscaledVal the specified `BigInt` value + * @param scale the scale + * @param mc the precision and rounding mode for creation of this value and future operations on it + * @return the constructed `BigDecimal` + */ def apply(unscaledVal: BigInt, scale: Int, mc: MathContext): BigDecimal = new BigDecimal(new BigDec(unscaledVal.bigInteger, scale, mc), mc) + /** Constructs a `BigDecimal` from a `java.math.BigDecimal`. */ def apply(bd: BigDec): BigDecimal = apply(bd, defaultMathContext) + + @deprecated("This method appears to round a java.math.BigDecimal but actually doesn't. Use new BigDecimal(bd, mc) instead for no rounding, or BigDecimal.decimal(bd, mc) for rounding.", "2.11") def apply(bd: BigDec, mc: MathContext): BigDecimal = new BigDecimal(bd, mc) /** Implicit conversion from `Int` to `BigDecimal`. */ @@ -149,44 +340,123 @@ object BigDecimal { implicit def long2bigDecimal(l: Long): BigDecimal = apply(l) /** Implicit conversion from `Double` to `BigDecimal`. */ - implicit def double2bigDecimal(d: Double): BigDecimal = valueOf(d, defaultMathContext) + implicit def double2bigDecimal(d: Double): BigDecimal = decimal(d) /** Implicit conversion from `java.math.BigDecimal` to `scala.BigDecimal`. */ implicit def javaBigDecimal2bigDecimal(x: BigDec): BigDecimal = apply(x) } /** + * `BigDecimal` represents decimal floating-point numbers of arbitrary precision. + * By default, the precision approximately matches that of IEEE 128-bit floating + * point numbers (34 decimal digits, `HALF_EVEN` rounding mode). Within the range + * of IEEE binary128 numbers, `BigDecimal` will agree with `BigInt` for both + * equality and hash codes (and will agree with primitive types as well). Beyond + * that range--numbers with more than 4934 digits when written out in full--the + * `hashCode` of `BigInt` and `BigDecimal` is allowed to diverge due to difficulty + * in efficiently computing both the decimal representation in `BigDecimal` and the + * binary representation in `BigInt`. + * + * When creating a `BigDecimal` from a `Double` or `Float`, care must be taken as + * the binary fraction representation of `Double` and `Float` does not easily + * convert into a decimal representation. Three explicit schemes are available + * for conversion. `BigDecimal.decimal` will convert the floating-point number + * to a decimal text representation, and build a `BigDecimal` based on that. + * `BigDecimal.binary` will expand the binary fraction to the requested or default + * precision. `BigDecimal.exact` will expand the binary fraction to the + * full number of digits, thus producing the exact decimal value corrsponding to + * the binary fraction of that floating-point number. `BigDecimal` equality + * matches the decimal expansion of `Double`: `BigDecimal.decimal(0.1) == 0.1`. + * Note that since `0.1f != 0.1`, the same is not true for `Float`. Instead, + * `0.1f == BigDecimal.decimal((0.1f).toDouble)`. + * + * To test whether a `BigDecimal` number can be converted to a `Double` or + * `Float` and then back without loss of information by using one of these + * methods, test with `isDecimalDouble`, `isBinaryDouble`, or `isExactDouble` + * or the corresponding `Float` versions. Note that `BigInt`'s `isValidDouble` + * will agree with `isExactDouble`, not the `isDecimalDouble` used by default. + * + * `BigDecimal` uses the decimal representation of binary floating-point numbers + * to determine equality and hash codes. This yields different answers than + * conversion between `Long` and `Double` values, where the exact form is used. + * As always, since floating-point is a lossy representation, it is advisable to + * take care when assuming identity will be maintained across multiple conversions. + * + * `BigDecimal` maintains a `MathContext` that determines the rounding that + * is applied to certain calculations. In most cases, the value of the + * `BigDecimal` is also rounded to the precision specified by the `MathContext`. + * To create a `BigDecimal` with a different precision than its `MathContext`, + * use `new BigDecimal(new java.math.BigDecimal(...), mc)`. Rounding will + * be applied on those mathematical operations that can dramatically change the + * number of digits in a full representation, namely multiplication, division, + * and powers. The left-hand argument's `MathContext` always determines the + * degree of rounding, if any, and is the one propagated through arithmetic + * operations that do not apply rounding themselves. + * * @author Stephane Micheloud - * @version 1.0 + * @author Rex Kerr + * @version 1.1 */ -@deprecatedInheritance("This class will be made final.", "2.10.0") -class BigDecimal( - val bigDecimal: BigDec, - val mc: MathContext) +final class BigDecimal(val bigDecimal: BigDec, val mc: MathContext) extends ScalaNumber with ScalaNumericConversions with Serializable { def this(bigDecimal: BigDec) = this(bigDecimal, BigDecimal.defaultMathContext) import BigDecimal.RoundingMode._ - - /** Cuts way down on the wrapper noise. */ - private implicit def bigdec2BigDecimal(x: BigDec): BigDecimal = new BigDecimal(x, mc) - + import BigDecimal.{decimal, binary, exact} + + if (bigDecimal eq null) throw new IllegalArgumentException("null value for BigDecimal") + if (mc eq null) throw new IllegalArgumentException("null MathContext for BigDecimal") + + // There was an implicit to cut down on the wrapper noise for BigDec -> BigDecimal. + // However, this may mask introduction of surprising behavior (e.g. lack of rounding + // where one might expect it). Wrappers should be applied explicitly with an + // eye to correctness. + + // Sane hash code computation (which is surprisingly hard). + // Note--not lazy val because we can't afford the extra space. + private final var computedHashCode: Int = BigDecimal.hashCodeNotComputed + private final def computeHashCode(): Unit = { + computedHashCode = + if (isWhole && (precision - scale) < BigDecimal.maximumHashScale) toBigInt.hashCode + else if (isValidDouble) doubleValue.## + else { + val temp = bigDecimal.stripTrailingZeros + scala.util.hashing.MurmurHash3.mixLast( temp.scaleByPowerOfTen(temp.scale).toBigInteger.hashCode, temp.scale ) + } + } + /** Returns the hash code for this BigDecimal. - * Note that this does not use the underlying java object's - * hashCode because we compare BigDecimals with compareTo + * Note that this does not merely use the underlying java object's + * `hashCode` because we compare `BigDecimal`s with `compareTo` * which deems 2 == 2.00, whereas in java these are unequal - * with unequal hashCodes. - */ - override def hashCode(): Int = - if (isWhole) unifiedPrimitiveHashcode - else doubleValue.## + * with unequal `hashCode`s. These hash codes agree with `BigInt` + * for whole numbers up ~4934 digits (the range of IEEE 128 bit floating + * point). Beyond this, hash codes will disagree; this prevents the + * explicit represention of the `BigInt` form for `BigDecimal` values + * with large exponents. + */ + override def hashCode(): Int = { + if (computedHashCode == BigDecimal.hashCodeNotComputed) computeHashCode + computedHashCode + } - /** Compares this BigDecimal with the specified value for equality. + /** Compares this BigDecimal with the specified value for equality. Where `Float` and `Double` + * disagree, `BigDecimal` will agree with the `Double` value */ override def equals (that: Any): Boolean = that match { case that: BigDecimal => this equals that - case that: BigInt => this.toBigIntExact exists (that equals _) - case that: Double => isValidDouble && toDouble == that - case that: Float => isValidFloat && toFloat == that + case that: BigInt => + that.bitLength > (precision-scale-2)*BigDecimal.deci2binary && + this.toBigIntExact.exists(that equals _) + case that: Double => + !that.isInfinity && { + val d = toDouble + !d.isInfinity && d == that && equals(decimal(d)) + } + case that: Float => + !that.isInfinity && { + val f = toFloat + !f.isInfinity && f == that && equals(decimal(f.toDouble)) + } case _ => isValidLong && unifiedPrimitiveEquals(that) } override def isValidByte = noArithmeticException(toByteExact) @@ -194,26 +464,71 @@ extends ScalaNumber with ScalaNumericConversions with Serializable { override def isValidChar = isValidInt && toIntExact >= Char.MinValue && toIntExact <= Char.MaxValue override def isValidInt = noArithmeticException(toIntExact) def isValidLong = noArithmeticException(toLongExact) - /** Returns `true` iff this can be represented exactly by [[scala.Float]]; otherwise returns `false`. + /** Tests whether the value is a valid Float. "Valid" has several distinct meanings, however. Use + * `isExactFloat`, `isBinaryFloat`, or `isDecimalFloat`, depending on the intended meaning. + * By default, `decimal` creation is used, so `isDecimalFloat` is probably what you want. */ + @deprecated("What constitutes validity is unclear. Use `isExactFloat`, `isBinaryFloat`, or `isDecimalFloat` instead.", "2.11") def isValidFloat = { val f = toFloat - !f.isInfinity && bigDecimal.compareTo(new java.math.BigDecimal(f)) == 0 + !f.isInfinity && bigDecimal.compareTo(new BigDec(f.toDouble)) == 0 } - /** Returns `true` iff this can be represented exactly by [[scala.Double]]; otherwise returns `false`. + /** Tests whether the value is a valid Double. "Valid" has several distinct meanings, however. Use + * `isExactDouble`, `isBinaryDouble`, or `isDecimalDouble`, depending on the intended meaning. + * By default, `decimal` creation is used, so `isDecimalDouble` is probably what you want. */ + @deprecated("Validity has two distinct meanings. Use `isExactBinaryDouble` or `equivalentToDouble` instead.", "2.11") def isValidDouble = { val d = toDouble - !d.isInfinity && bigDecimal.compareTo(new java.math.BigDecimal(d)) == 0 + !d.isInfinity && bigDecimal.compareTo(new BigDec(d)) == 0 + } + + /** Tests whether this `BigDecimal` holds the decimal representation of a `Double`. */ + def isDecimalDouble = { + val d = toDouble + !d.isInfinity && equals(decimal(d)) + } + + /** Tests whether this `BigDecimal` holds the decimal representation of a `Float`. */ + def isDecimalFloat = { + val f = toFloat + !f.isInfinity && equals(decimal(f)) + } + + /** Tests whether this `BigDecimal` holds, to within precision, the binary representation of a `Double`. */ + def isBinaryDouble = { + val d = toDouble + !d.isInfinity && equals(binary(d,mc)) + } + + /** Tests whether this `BigDecimal` holds, to within precision, the binary representation of a `Float`. */ + def isBinaryFloat = { + val f = toFloat + !f.isInfinity && equals(binary(f,mc)) + } + + /** Tests whether this `BigDecimal` holds the exact expansion of a `Double`'s binary fractional form into base 10. */ + def isExactDouble = { + val d = toDouble + !d.isInfinity && equals(exact(d)) + } + + /** Tests whether this `BigDecimal` holds the exact expansion of a `Float`'s binary fractional form into base 10. */ + def isExactFloat = { + val f = toFloat + !f.isInfinity && equals(exact(f.toDouble)) } + private def noArithmeticException(body: => Unit): Boolean = { try { body ; true } catch { case _: ArithmeticException => false } } - def isWhole() = (this remainder 1) == BigDecimal(0) + def isWhole() = scale <= 0 || bigDecimal.stripTrailingZeros.scale <= 0 + def underlying = bigDecimal + /** Compares this BigDecimal with the specified BigDecimal for equality. */ @@ -241,60 +556,66 @@ extends ScalaNumber with ScalaNumericConversions with Serializable { /** Addition of BigDecimals */ - def + (that: BigDecimal): BigDecimal = this.bigDecimal.add(that.bigDecimal) + def + (that: BigDecimal): BigDecimal = new BigDecimal(this.bigDecimal add that.bigDecimal, mc) /** Subtraction of BigDecimals */ - def - (that: BigDecimal): BigDecimal = this.bigDecimal.subtract(that.bigDecimal) + def - (that: BigDecimal): BigDecimal = new BigDecimal(this.bigDecimal subtract that.bigDecimal, mc) /** Multiplication of BigDecimals */ - def * (that: BigDecimal): BigDecimal = this.bigDecimal.multiply(that.bigDecimal, mc) + def * (that: BigDecimal): BigDecimal = new BigDecimal(this.bigDecimal.multiply(that.bigDecimal, mc), mc) /** Division of BigDecimals */ - def / (that: BigDecimal): BigDecimal = this.bigDecimal.divide(that.bigDecimal, mc) + def / (that: BigDecimal): BigDecimal = new BigDecimal(this.bigDecimal.divide(that.bigDecimal, mc), mc) /** Division and Remainder - returns tuple containing the result of - * divideToIntegralValue and the remainder. + * divideToIntegralValue and the remainder. The computation is exact: no rounding is applied. */ def /% (that: BigDecimal): (BigDecimal, BigDecimal) = this.bigDecimal.divideAndRemainder(that.bigDecimal) match { - case Array(q, r) => (q, r) + case Array(q, r) => (new BigDecimal(q, mc), new BigDecimal(r, mc)) } /** Divide to Integral value. */ def quot (that: BigDecimal): BigDecimal = - this.bigDecimal.divideToIntegralValue(that.bigDecimal) + new BigDecimal(this.bigDecimal divideToIntegralValue that.bigDecimal, mc) - /** Returns the minimum of this and that + /** Returns the minimum of this and that, or this if the two are equal */ - def min (that: BigDecimal): BigDecimal = this.bigDecimal min that.bigDecimal - - /** Returns the maximum of this and that + def min (that: BigDecimal): BigDecimal = (this compare that) match { + case x if x <= 0 => this + case _ => that + } + + /** Returns the maximum of this and that, or this if the two are equal */ - def max (that: BigDecimal): BigDecimal = this.bigDecimal max that.bigDecimal - + def max (that: BigDecimal): BigDecimal = (this compare that) match { + case x if x >= 0 => this + case _ => that + } + /** Remainder after dividing this by that. */ - def remainder (that: BigDecimal): BigDecimal = this.bigDecimal.remainder(that.bigDecimal) + def remainder (that: BigDecimal): BigDecimal = new BigDecimal(this.bigDecimal remainder that.bigDecimal, mc) /** Remainder after dividing this by that. */ - def % (that: BigDecimal): BigDecimal = this.remainder(that) + def % (that: BigDecimal): BigDecimal = this remainder that /** Returns a BigDecimal whose value is this ** n. */ - def pow (n: Int): BigDecimal = this.bigDecimal.pow(n, mc) + def pow (n: Int): BigDecimal = new BigDecimal(this.bigDecimal.pow(n, mc), mc) /** Returns a BigDecimal whose value is the negation of this BigDecimal */ - def unary_- : BigDecimal = this.bigDecimal.negate() + def unary_- : BigDecimal = new BigDecimal(this.bigDecimal.negate(), mc) /** Returns the absolute value of this BigDecimal */ - def abs: BigDecimal = this.bigDecimal.abs + def abs: BigDecimal = if (signum < 0) unary_- else this /** Returns the sign of this BigDecimal, i.e. * -1 if it is less than 0, @@ -307,9 +628,19 @@ extends ScalaNumber with ScalaNumericConversions with Serializable { */ def precision: Int = this.bigDecimal.precision() - /** Returns a BigDecimal rounded according to the MathContext settings. + /** Returns a BigDecimal rounded according to the supplied MathContext settings, but + * preserving its own MathContext for future operations. */ - def round(mc: MathContext): BigDecimal = this.bigDecimal round mc + def round(mc: MathContext): BigDecimal = { + val r = this.bigDecimal round mc + if (r eq bigDecimal) this else new BigDecimal(r, this.mc) + } + + /** Returns a `BigDecimal` rounded according to its own `MathContext` */ + def rounded: BigDecimal = { + val r = bigDecimal round mc + if (r eq bigDecimal) this else new BigDecimal(r, mc) + } /** Returns the scale of this `BigDecimal`. */ @@ -317,19 +648,22 @@ extends ScalaNumber with ScalaNumericConversions with Serializable { /** Returns the size of an ulp, a unit in the last place, of this BigDecimal. */ - def ulp: BigDecimal = this.bigDecimal.ulp + def ulp: BigDecimal = new BigDecimal(this.bigDecimal.ulp, mc) - /** Returns a new BigDecimal based on the supplied MathContext. + /** Returns a new BigDecimal based on the supplied MathContext, rounded as needed. */ - def apply(mc: MathContext): BigDecimal = BigDecimal(this.bigDecimal.toString, mc) + def apply(mc: MathContext): BigDecimal = new BigDecimal(this.bigDecimal round mc, mc) /** Returns a `BigDecimal` whose scale is the specified value, and whose value is * numerically equal to this BigDecimal's. */ - def setScale(scale: Int): BigDecimal = this.bigDecimal setScale scale + def setScale(scale: Int): BigDecimal = + if (this.scale == scale) this + else new BigDecimal(this.bigDecimal setScale scale, mc) def setScale(scale: Int, mode: RoundingMode): BigDecimal = - this.bigDecimal.setScale(scale, mode.id) + if (this.scale == scale) this + else new BigDecimal(this.bigDecimal.setScale(scale, mode.id), mc) /** Converts this BigDecimal to a Byte. * If the BigDecimal is too big to fit in a Byte, only the low-order 8 bits are returned. @@ -339,21 +673,21 @@ extends ScalaNumber with ScalaNumericConversions with Serializable { override def byteValue = intValue.toByte /** Converts this BigDecimal to a Short. - * If the BigDecimal is too big to fit in a Byte, only the low-order 16 bits are returned. + * If the BigDecimal is too big to fit in a Short, only the low-order 16 bits are returned. * Note that this conversion can lose information about the overall magnitude of the * BigDecimal value as well as return a result with the opposite sign. */ override def shortValue = intValue.toShort /** Converts this BigDecimal to a Char. - * If the BigDecimal is too big to fit in a char, only the low-order 16 bits are returned. + * If the BigDecimal is too big to fit in a Char, only the low-order 16 bits are returned. * Note that this conversion can lose information about the overall magnitude of the * BigDecimal value and that it always returns a positive result. */ def charValue = intValue.toChar /** Converts this BigDecimal to an Int. - * If the BigDecimal is too big to fit in a char, only the low-order 32 bits + * If the BigDecimal is too big to fit in an Int, only the low-order 32 bits * are returned. Note that this conversion can lose information about the * overall magnitude of the BigDecimal value as well as return a result with * the opposite sign. @@ -361,7 +695,7 @@ extends ScalaNumber with ScalaNumericConversions with Serializable { def intValue = this.bigDecimal.intValue /** Converts this BigDecimal to a Long. - * If the BigDecimal is too big to fit in a char, only the low-order 64 bits + * If the BigDecimal is too big to fit in a Long, only the low-order 64 bits * are returned. Note that this conversion can lose information about the * overall magnitude of the BigDecimal value as well as return a result with * the opposite sign. @@ -444,8 +778,11 @@ extends ScalaNumber with ScalaNumericConversions with Serializable { * can be done losslessly, returning Some(BigInt) or None. */ def toBigIntExact(): Option[BigInt] = - try Some(new BigInt(this.bigDecimal.toBigIntegerExact())) - catch { case _: ArithmeticException => None } + if (isWhole()) { + try Some(new BigInt(this.bigDecimal.toBigIntegerExact())) + catch { case _: ArithmeticException => None } + } + else None /** Returns the decimal String representation of this BigDecimal. */ diff --git a/src/library/scala/math/BigInt.scala b/src/library/scala/math/BigInt.scala index 58838f13a7..689fc0c3e1 100644 --- a/src/library/scala/math/BigInt.scala +++ b/src/library/scala/math/BigInt.scala @@ -6,7 +6,8 @@ ** |/ ** \* */ -package scala.math +package scala +package math import java.math.BigInteger import scala.language.implicitConversions @@ -23,12 +24,6 @@ object BigInt { private val cache = new Array[BigInt](maxCached - minCached + 1) private val minusOne = BigInteger.valueOf(-1) - @deprecated("Use Long.MinValue", "2.9.0") - val MinLong = BigInt(Long.MinValue) - - @deprecated("Use Long.MaxValue", "2.9.0") - val MaxLong = BigInt(Long.MaxValue) - /** Constructs a `BigInt` whose value is equal to that of the * specified integer value. * @@ -39,9 +34,9 @@ object BigInt { if (minCached <= i && i <= maxCached) { val offset = i - minCached var n = cache(offset) - if (n eq null) { n = new BigInt(BigInteger.valueOf(i)); cache(offset) = n } + if (n eq null) { n = new BigInt(BigInteger.valueOf(i.toLong)); cache(offset) = n } n - } else new BigInt(BigInteger.valueOf(i)) + } else new BigInt(BigInteger.valueOf(i.toLong)) /** Constructs a `BigInt` whose value is equal to that of the * specified long value. @@ -114,18 +109,17 @@ object BigInt { * @author Martin Odersky * @version 1.0, 15/07/2003 */ -@deprecatedInheritance("This class will be made final.", "2.10.0") -class BigInt(val bigInteger: BigInteger) extends ScalaNumber with ScalaNumericConversions with Serializable { +final class BigInt(val bigInteger: BigInteger) extends ScalaNumber with ScalaNumericConversions with Serializable { /** Returns the hash code for this BigInt. */ override def hashCode(): Int = - if (isValidLong) unifiedPrimitiveHashcode + if (isValidLong) unifiedPrimitiveHashcode() else bigInteger.## /** Compares this BigInt with the specified value for equality. */ override def equals(that: Any): Boolean = that match { case that: BigInt => this equals that - case that: BigDecimal => that.toBigIntExact exists (this equals _) + case that: BigDecimal => that equals this case that: Double => isValidDouble && toDouble == that case that: Float => isValidFloat && toFloat == that case x => isValidLong && unifiedPrimitiveEquals(x) @@ -295,9 +289,6 @@ class BigInt(val bigInteger: BigInteger) extends ScalaNumber with ScalaNumericCo */ def signum: Int = this.bigInteger.signum() - @deprecated("Use ~bigInt (the unary_~ method) instead", "2.10.0") - def ~ : BigInt = ~this - /** Returns the bitwise complement of this BigInt */ def unary_~ : BigInt = new BigInt(this.bigInteger.not()) @@ -364,7 +355,7 @@ class BigInt(val bigInteger: BigInteger) extends ScalaNumber with ScalaNumericCo def charValue = intValue.toChar /** Converts this BigInt to an <tt>int</tt>. - * If the BigInt is too big to fit in a int, only the low-order 32 bits + * If the BigInt is too big to fit in an int, only the low-order 32 bits * are returned. Note that this conversion can lose information about the * overall magnitude of the BigInt value as well as return a result with * the opposite sign. diff --git a/src/library/scala/math/Equiv.scala b/src/library/scala/math/Equiv.scala index 5f5e049941..45b2b3629d 100644 --- a/src/library/scala/math/Equiv.scala +++ b/src/library/scala/math/Equiv.scala @@ -6,7 +6,8 @@ ** |/ ** \* */ -package scala.math +package scala +package math import java.util.Comparator diff --git a/src/library/scala/math/Fractional.scala b/src/library/scala/math/Fractional.scala index ca33675b0a..b7e0ed5471 100644 --- a/src/library/scala/math/Fractional.scala +++ b/src/library/scala/math/Fractional.scala @@ -6,7 +6,8 @@ ** |/ ** \* */ -package scala.math +package scala +package math import scala.language.implicitConversions diff --git a/src/library/scala/math/Integral.scala b/src/library/scala/math/Integral.scala index f3684c4e5d..ff1f695f6d 100644 --- a/src/library/scala/math/Integral.scala +++ b/src/library/scala/math/Integral.scala @@ -8,7 +8,8 @@ -package scala.math +package scala +package math import scala.language.implicitConversions diff --git a/src/library/scala/math/Numeric.scala b/src/library/scala/math/Numeric.scala index 5a76f4f5f2..eafbf96993 100644 --- a/src/library/scala/math/Numeric.scala +++ b/src/library/scala/math/Numeric.scala @@ -6,7 +6,8 @@ ** |/ ** \* */ -package scala.math +package scala +package math import scala.language.implicitConversions @@ -50,9 +51,9 @@ object Numeric { def negate(x: Int): Int = -x def fromInt(x: Int): Int = x def toInt(x: Int): Int = x - def toLong(x: Int): Long = x - def toFloat(x: Int): Float = x - def toDouble(x: Int): Double = x + def toLong(x: Int): Long = x.toLong + def toFloat(x: Int): Float = x.toFloat + def toDouble(x: Int): Double = x.toDouble } implicit object IntIsIntegral extends IntIsIntegral with Ordering.IntOrdering @@ -108,11 +109,11 @@ object Numeric { def quot(x: Long, y: Long): Long = x / y def rem(x: Long, y: Long): Long = x % y def negate(x: Long): Long = -x - def fromInt(x: Int): Long = x + def fromInt(x: Int): Long = x.toLong def toInt(x: Long): Int = x.toInt def toLong(x: Long): Long = x - def toFloat(x: Long): Float = x - def toDouble(x: Long): Double = x + def toFloat(x: Long): Float = x.toFloat + def toDouble(x: Long): Double = x.toDouble } implicit object LongIsIntegral extends LongIsIntegral with Ordering.LongOrdering @@ -121,11 +122,13 @@ object Numeric { def minus(x: Float, y: Float): Float = x - y def times(x: Float, y: Float): Float = x * y def negate(x: Float): Float = -x - def fromInt(x: Int): Float = x + def fromInt(x: Int): Float = x.toFloat def toInt(x: Float): Int = x.toInt def toLong(x: Float): Long = x.toLong def toFloat(x: Float): Float = x - def toDouble(x: Float): Double = x + def toDouble(x: Float): Double = x.toDouble + // logic in Numeric base trait mishandles abs(-0.0f) + override def abs(x: Float): Float = math.abs(x) } trait FloatIsFractional extends FloatIsConflicted with Fractional[Float] { def div(x: Float, y: Float): Float = x / y @@ -143,11 +146,13 @@ object Numeric { def minus(x: Double, y: Double): Double = x - y def times(x: Double, y: Double): Double = x * y def negate(x: Double): Double = -x - def fromInt(x: Int): Double = x + def fromInt(x: Int): Double = x.toDouble def toInt(x: Double): Int = x.toInt def toLong(x: Double): Long = x.toLong def toFloat(x: Double): Float = x.toFloat def toDouble(x: Double): Double = x + // logic in Numeric base trait mishandles abs(-0.0) + override def abs(x: Double): Double = math.abs(x) } trait DoubleIsFractional extends DoubleIsConflicted with Fractional[Double] { def div(x: Double, y: Double): Double = x / y diff --git a/src/library/scala/math/Ordered.scala b/src/library/scala/math/Ordered.scala index e8be92eb4a..51f2765a63 100644 --- a/src/library/scala/math/Ordered.scala +++ b/src/library/scala/math/Ordered.scala @@ -6,7 +6,8 @@ ** |/ ** \* */ -package scala.math +package scala +package math import scala.language.implicitConversions diff --git a/src/library/scala/math/Ordering.scala b/src/library/scala/math/Ordering.scala index 11b12050c9..d1a4e7c35c 100644 --- a/src/library/scala/math/Ordering.scala +++ b/src/library/scala/math/Ordering.scala @@ -26,14 +26,14 @@ import scala.language.{implicitConversions, higherKinds} * val pairs = Array(("a", 5, 2), ("c", 3, 1), ("b", 1, 3)) * * // sort by 2nd element - * Sorting.quickSort(pairs)(Ordering.by[(String, Int, Int), Int](_._2)) + * Sorting.quickSort(pairs)(Ordering.by[(String, Int, Int), Int](_._2) * * // sort by the 3rd element, then 1st * Sorting.quickSort(pairs)(Ordering[(Int, String)].on(x => (x._3, x._1))) * }}} * * An Ordering[T] is implemented by specifying compare(a:T, b:T), which - * decides how to order to instances a and b. Instances of Ordering[T] can be + * decides how to order two instances a and b. Instances of Ordering[T] can be * used by things like scala.util.Sorting to sort collections like Array[T]. * * For example: @@ -173,7 +173,7 @@ object Ordering extends LowPriorityOrderingImplicits { val ye = y.iterator while (xe.hasNext && ye.hasNext) { - val res = ord.compare(xe.next, ye.next) + val res = ord.compare(xe.next(), ye.next()) if (res != 0) return res } @@ -347,7 +347,7 @@ object Ordering extends LowPriorityOrderingImplicits { val ye = y.iterator while (xe.hasNext && ye.hasNext) { - val res = ord.compare(xe.next, ye.next) + val res = ord.compare(xe.next(), ye.next()) if (res != 0) return res } diff --git a/src/library/scala/math/PartialOrdering.scala b/src/library/scala/math/PartialOrdering.scala index a9e317d536..9e35381528 100644 --- a/src/library/scala/math/PartialOrdering.scala +++ b/src/library/scala/math/PartialOrdering.scala @@ -6,7 +6,8 @@ ** |/ ** \* */ -package scala.math +package scala +package math /** A trait for representing partial orderings. It is important to * distinguish between a type that has a partial order and a representation diff --git a/src/library/scala/math/PartiallyOrdered.scala b/src/library/scala/math/PartiallyOrdered.scala index 7823e5b396..f58210d6a7 100644 --- a/src/library/scala/math/PartiallyOrdered.scala +++ b/src/library/scala/math/PartiallyOrdered.scala @@ -8,7 +8,8 @@ -package scala.math +package scala +package math /** A class for partially ordered data. * diff --git a/src/library/scala/math/ScalaNumber.java b/src/library/scala/math/ScalaNumber.java index 7345147b0d..f03ba7bf08 100644 --- a/src/library/scala/math/ScalaNumber.java +++ b/src/library/scala/math/ScalaNumber.java @@ -6,8 +6,6 @@ ** |/ ** \* */ - - package scala.math; /** A marker class for Number types introduced by Scala diff --git a/src/library/scala/math/ScalaNumericConversions.scala b/src/library/scala/math/ScalaNumericConversions.scala index 6ddf48d03b..0006133b13 100644 --- a/src/library/scala/math/ScalaNumericConversions.scala +++ b/src/library/scala/math/ScalaNumericConversions.scala @@ -6,9 +6,8 @@ ** |/ ** \* */ -package scala.math - -import java.{ lang => jl } +package scala +package math /** A slightly more specific conversion trait for classes which * extend ScalaNumber (which excludes value classes.) @@ -21,6 +20,7 @@ trait ScalaNumericConversions extends ScalaNumber with ScalaNumericAnyConversion * across all the numeric types, suitable for use in value classes. */ trait ScalaNumericAnyConversions extends Any { + /** @return `'''true'''` if this number has no decimal component, `'''false'''` otherwise. */ def isWhole(): Boolean def underlying(): Any @@ -34,37 +34,37 @@ trait ScalaNumericAnyConversions extends Any { /** Returns the value of this as a [[scala.Char]]. This may involve * rounding or truncation. */ - def toChar = intValue.toChar + def toChar = intValue().toChar /** Returns the value of this as a [[scala.Byte]]. This may involve * rounding or truncation. */ - def toByte = byteValue + def toByte = byteValue() /** Returns the value of this as a [[scala.Short]]. This may involve * rounding or truncation. */ - def toShort = shortValue + def toShort = shortValue() /** Returns the value of this as an [[scala.Int]]. This may involve * rounding or truncation. */ - def toInt = intValue + def toInt = intValue() /** Returns the value of this as a [[scala.Long]]. This may involve * rounding or truncation. */ - def toLong = longValue + def toLong = longValue() /** Returns the value of this as a [[scala.Float]]. This may involve * rounding or truncation. */ - def toFloat = floatValue + def toFloat = floatValue() /** Returns the value of this as a [[scala.Double]]. This may involve * rounding or truncation. */ - def toDouble = doubleValue + def toDouble = doubleValue() /** Returns `true` iff this has a zero fractional part, and is within the * range of [[scala.Byte]] MinValue and MaxValue; otherwise returns `false`. diff --git a/src/library/scala/math/package.scala b/src/library/scala/math/package.scala index cb033bda2c..58ece8a05b 100644 --- a/src/library/scala/math/package.scala +++ b/src/library/scala/math/package.scala @@ -16,12 +16,12 @@ package object math { /** The `double` value that is closer than any other to `e`, the base of * the natural logarithms. */ - val E = java.lang.Math.E + @inline final val E = java.lang.Math.E /** The `double` value that is closer than any other to `pi`, the ratio of * the circumference of a circle to its diameter. */ - val Pi = java.lang.Math.PI + @inline final val Pi = java.lang.Math.PI /** Returns a `double` value with a positive sign, greater than or equal * to `0.0` and less than `1.0`. @@ -62,7 +62,7 @@ package object math { def sqrt(x: Double): Double = java.lang.Math.sqrt(x) def IEEEremainder(x: Double, y: Double): Double = java.lang.Math.IEEEremainder(x, y) - def ceil(x: Double): Double = java.lang.Math.ceil(x) + def ceil(x: Double): Double = java.lang.Math.ceil(x) def floor(x: Double): Double = java.lang.Math.floor(x) /** Returns the `double` value that is closest in value to the @@ -93,31 +93,47 @@ package object math { */ def pow(x: Double, y: Double): Double = java.lang.Math.pow(x, y) - /** Returns the closest `long` to the argument. + /** There is no reason to round a `Long`, but this method prevents unintended conversion to `Float` followed by rounding to `Int`. */ + @deprecated("This is an integer type; there is no reason to round it. Perhaps you meant to call this with a floating-point value?", "2.11.0") + def round(x: Long): Long = x + + /** Returns the closest `Int` to the argument. * - * @param x a floating-point value to be rounded to a `long`. - * @return the value of the argument rounded to the nearest`long` value. + * @param x a floating-point value to be rounded to a `Int`. + * @return the value of the argument rounded to the nearest `Int` value. */ def round(x: Float): Int = java.lang.Math.round(x) + + /** Returns the closest `Long` to the argument. + * + * @param x a floating-point value to be rounded to a `Long`. + * @return the value of the argument rounded to the nearest`long` value. + */ def round(x: Double): Long = java.lang.Math.round(x) - def abs(x: Int): Int = java.lang.Math.abs(x) - def abs(x: Long): Long = java.lang.Math.abs(x) - def abs(x: Float): Float = java.lang.Math.abs(x) + + def abs(x: Int): Int = java.lang.Math.abs(x) + def abs(x: Long): Long = java.lang.Math.abs(x) + def abs(x: Float): Float = java.lang.Math.abs(x) def abs(x: Double): Double = java.lang.Math.abs(x) - def max(x: Int, y: Int): Int = java.lang.Math.max(x, y) - def max(x: Long, y: Long): Long = java.lang.Math.max(x, y) - def max(x: Float, y: Float): Float = java.lang.Math.max(x, y) + def max(x: Int, y: Int): Int = java.lang.Math.max(x, y) + def max(x: Long, y: Long): Long = java.lang.Math.max(x, y) + def max(x: Float, y: Float): Float = java.lang.Math.max(x, y) def max(x: Double, y: Double): Double = java.lang.Math.max(x, y) - def min(x: Int, y: Int): Int = java.lang.Math.min(x, y) - def min(x: Long, y: Long): Long = java.lang.Math.min(x, y) - def min(x: Float, y: Float): Float = java.lang.Math.min(x, y) + def min(x: Int, y: Int): Int = java.lang.Math.min(x, y) + def min(x: Long, y: Long): Long = java.lang.Math.min(x, y) + def min(x: Float, y: Float): Float = java.lang.Math.min(x, y) def min(x: Double, y: Double): Double = java.lang.Math.min(x, y) - def signum(x: Int): Int = java.lang.Integer.signum(x) - def signum(x: Long): Long = java.lang.Long.signum(x) - def signum(x: Float): Float = java.lang.Math.signum(x) + /** Note that these are not pure forwarders to the java versions. + * In particular, the return type of java.lang.Long.signum is Int, + * but here it is widened to Long so that each overloaded variant + * will return the same numeric type it is passed. + */ + def signum(x: Int): Int = java.lang.Integer.signum(x) + def signum(x: Long): Long = java.lang.Long.signum(x) + def signum(x: Float): Float = java.lang.Math.signum(x) def signum(x: Double): Double = java.lang.Math.signum(x) // ----------------------------------------------------------------------- diff --git a/src/library/scala/package.scala b/src/library/scala/package.scala index 84f6f0be9c..224112c11c 100644 --- a/src/library/scala/package.scala +++ b/src/library/scala/package.scala @@ -34,12 +34,6 @@ package object scala { override def toString = "object AnyRef" } - @deprecated("instead of `@serializable class C`, use `class C extends Serializable`", "2.9.0") - type serializable = annotation.serializable - - @deprecated("instead of `@cloneable class C`, use `class C extends Cloneable`", "2.10.0") - type cloneable = annotation.cloneable - type TraversableOnce[+A] = scala.collection.TraversableOnce[A] type Traversable[+A] = scala.collection.Traversable[A] @@ -95,7 +89,10 @@ package object scala { val Equiv = scala.math.Equiv type Fractional[T] = scala.math.Fractional[T] + val Fractional = scala.math.Fractional + type Integral[T] = scala.math.Integral[T] + val Integral = scala.math.Integral type Numeric[T] = scala.math.Numeric[T] val Numeric = scala.math.Numeric @@ -121,14 +118,12 @@ package object scala { // Annotations which we might move to annotation.* /* type SerialVersionUID = annotation.SerialVersionUID - type cloneable = annotation.cloneable type deprecated = annotation.deprecated type deprecatedName = annotation.deprecatedName type inline = annotation.inline type native = annotation.native - type noinline = noannotation.inline + type noinline = annotation.noinline type remote = annotation.remote - type serializable = annotation.serializable type specialized = annotation.specialized type transient = annotation.transient type throws = annotation.throws diff --git a/src/library/scala/parallel/Future.scala b/src/library/scala/parallel/Future.scala deleted file mode 100644 index e255a5772b..0000000000 --- a/src/library/scala/parallel/Future.scala +++ /dev/null @@ -1,39 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2005-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala.parallel - - - -/** A future is a function without parameters that will block the caller if - * the parallel computation associated with the function is not completed. - * - * @tparam R the type of the result - * - * @since 2.9 - */ -@deprecated("Use `scala.concurrent.Future` instead.", "2.10.0") -trait Future[@specialized +R] extends (() => R) { - /** Returns a result once the parallel computation completes. If the - * computation produced an exception, an exception is forwarded. - * - * '''Note:''' creating a circular dependency between futures by calling - * this method will result in a deadlock. - * - * @return the result - * @throws the exception that was thrown during a parallel computation - */ - def apply(): R - - /** Returns `true` if the parallel computation is completed. - * - * @return `true` if the parallel computation is completed, `false` otherwise - */ - def isDone(): Boolean -} - diff --git a/src/library/scala/parallel/package.scala.disabled b/src/library/scala/parallel/package.scala.disabled deleted file mode 100644 index 45f5470d03..0000000000 --- a/src/library/scala/parallel/package.scala.disabled +++ /dev/null @@ -1,178 +0,0 @@ -package scala - - - -import scala.concurrent.forkjoin._ - - -/** This package object contains various parallel operations. - * - * @define invokingPar - * Invoking a parallel computation creates a future which will - * hold the result of the computation once it completes. Querying - * the result of a future before its parallel computation has completed - * will block the caller. For all practical concerns, the dependency - * chain obtained by querying results of unfinished futures can have - * arbitrary lengths. However, care must be taken not to create a - * circular dependency, as this will result in a deadlock. - * - * Additionally, if the parallel computation performs a blocking call - * (e.g. an I/O operation or waiting for a lock) other than waiting for a future, - * it should do so by invoking the `block` method. This is another - * form of waiting that could potentially create a circular dependency, - * an the user should take care not to do this. - * - * Users should be aware that invoking a parallel computation has a - * certain overhead. Parallel computations should not be invoked for - * small computations, as this can lead to bad performance. A rule of the - * thumb is having parallel computations equivalent to a loop - * with 50000 arithmetic operations (at least). If a parallel computation - * is invoked within another parallel computation, then it should be - * computationally equivalent to a loop with 10000 arithmetic operations. - */ -package object parallel { - - private[scala] val forkjoinpool = new ForkJoinPool() - - private class Task[T](body: =>T) extends RecursiveTask[T] with Future[T] { - def compute = body - def apply() = join() - } - - private final def newTask[T](body: =>T) = new Task[T](body) - - private final def executeTask[T](task: RecursiveTask[T]) { - if (Thread.currentThread().isInstanceOf[ForkJoinWorkerThread]) task.fork - else forkjoinpool.execute(task) - } - - /* public methods */ - - /** Performs a call which can potentially block execution. - * - * Example: - * {{{ - * val lock = new ReentrantLock - * - * // ... do something ... - * - * blocking { - * if (!lock.hasLock) lock.lock() - * } - * }}} - * - * '''Note:''' calling methods that wait arbitrary amounts of time - * (e.g. for I/O operations or locks) may severely decrease performance - * or even result in deadlocks. This does not include waiting for - * results of futures. - */ - def blocking[T](body: =>T): T = { - if (Thread.currentThread().isInstanceOf[ForkJoinWorkerThread]) { - val blocker = new ForkJoinPool.ManagedBlocker { - @volatile var done = false - @volatile var result: Any = _ - def block() = { - result = body - done = true - true - } - def isReleasable() = done - } - ForkJoinPool.managedBlock(blocker, true) - blocker.result.asInstanceOf[T] - } else body - } - - /** Starts a parallel computation and returns a future. - * - * $invokingPar - * - * @tparam T the type of the result of the parallel computation - * @param body the computation to be invoked in parallel - * @return a future with the result - */ - def par[T](body: =>T): Future[T] = { - val task = newTask(body) - executeTask(task) - task - } - - /** Starts 2 parallel computations and returns a future. - * - * $invokingPar - * - * @tparam T1 the type of the result of 1st the parallel computation - * @tparam T2 the type of the result of 2nd the parallel computation - * @param b1 the 1st computation to be invoked in parallel - * @param b2 the 2nd computation to be invoked in parallel - * @return a tuple of futures corresponding to parallel computations - */ - def par[T1, T2](b1: =>T1, b2: =>T2): (Future[T1], Future[T2]) = { - val t1 = newTask(b1) - executeTask(t1) - val t2 = newTask(b2) - executeTask(t2) - (t1, t2) - } - - /** Starts 3 parallel computations and returns a future. - * - * $invokingPar - * - * @tparam T1 the type of the result of 1st the parallel computation - * @tparam T2 the type of the result of 2nd the parallel computation - * @tparam T3 the type of the result of 3rd the parallel computation - * @param b1 the 1st computation to be invoked in parallel - * @param b2 the 2nd computation to be invoked in parallel - * @param b3 the 3rd computation to be invoked in parallel - * @return a tuple of futures corresponding to parallel computations - */ - def par[T1, T2, T3](b1: =>T1, b2: =>T2, b3: =>T3): (Future[T1], Future[T2], Future[T3]) = { - val t1 = newTask(b1) - executeTask(t1) - val t2 = newTask(b2) - executeTask(t2) - val t3 = newTask(b3) - executeTask(t3) - (t1, t2, t3) - } - - /** Starts 4 parallel computations and returns a future. - * - * $invokingPar - * - * @tparam T1 the type of the result of 1st the parallel computation - * @tparam T2 the type of the result of 2nd the parallel computation - * @tparam T3 the type of the result of 3rd the parallel computation - * @tparam T4 the type of the result of 4th the parallel computation - * @param b1 the 1st computation to be invoked in parallel - * @param b2 the 2nd computation to be invoked in parallel - * @param b3 the 3rd computation to be invoked in parallel - * @param b4 the 4th computation to be invoked in parallel - * @return a tuple of futures corresponding to parallel computations - */ - def par[T1, T2, T3, T4](b1: =>T1, b2: =>T2, b3: =>T3, b4: =>T4): (Future[T1], Future[T2], Future[T3], Future[T4]) = { - val t1 = newTask(b1) - executeTask(t1) - val t2 = newTask(b2) - executeTask(t2) - val t3 = newTask(b3) - executeTask(t3) - val t4 = newTask(b4) - executeTask(t4) - (t1, t2, t3, t4) - } - -} - - - - - - - - - - - - diff --git a/src/library/scala/ref/SoftReference.scala b/src/library/scala/ref/SoftReference.scala index b414db6e97..e4ce667981 100644 --- a/src/library/scala/ref/SoftReference.scala +++ b/src/library/scala/ref/SoftReference.scala @@ -13,7 +13,8 @@ package scala.ref * @author Sean McDirmid */ class SoftReference[+T <: AnyRef](value : T, queue : ReferenceQueue[T]) extends ReferenceWrapper[T] { - def this(value : T) = this(value, null); + def this(value : T) = this(value, null) + val underlying: java.lang.ref.SoftReference[_ <: T] = new SoftReferenceWithWrapper[T](value, queue, this) } diff --git a/src/library/scala/ref/WeakReference.scala b/src/library/scala/ref/WeakReference.scala index 6eb4899e3f..6ee40aed5c 100644 --- a/src/library/scala/ref/WeakReference.scala +++ b/src/library/scala/ref/WeakReference.scala @@ -10,7 +10,7 @@ package scala.ref /** - * A wrapper class for java.lag.ref.WeakReference + * A wrapper class for java.lang.ref.WeakReference * The new functionality is (1) results are Option values, instead of using null. * (2) There is an extractor that maps the weak reference itself into an option. * @author Sean McDirmid @@ -29,7 +29,7 @@ object WeakReference { /** Optionally returns the referenced value, or `None` if that value no longer exists */ def unapply[T <: AnyRef](wr: WeakReference[T]): Option[T] = { - val x = wr.underlying.get + val x = wr.underlying.get if (x != null) Some(x) else None } } diff --git a/src/library/scala/reflect/ClassManifestDeprecatedApis.scala b/src/library/scala/reflect/ClassManifestDeprecatedApis.scala index 0a3d818fb9..ca7a3cddb8 100644 --- a/src/library/scala/reflect/ClassManifestDeprecatedApis.scala +++ b/src/library/scala/reflect/ClassManifestDeprecatedApis.scala @@ -6,7 +6,8 @@ ** |/ ** \* */ -package scala.reflect +package scala +package reflect import scala.collection.mutable.{ WrappedArray, ArrayBuilder } import java.lang.{ Class => jClass } @@ -15,6 +16,7 @@ import java.lang.{ Class => jClass } trait ClassManifestDeprecatedApis[T] extends OptManifest[T] { self: ClassManifest[T] => + // Still in use in target test.junit.comp. @deprecated("Use runtimeClass instead", "2.10.0") def erasure: jClass[_] = runtimeClass @@ -63,12 +65,12 @@ trait ClassManifestDeprecatedApis[T] extends OptManifest[T] { // when the erasure is the same, even before considering variance. !cannotMatch && { // this part is wrong for not considering variance - if (this.erasure == that.erasure) + if (this.runtimeClass == that.runtimeClass) subargs(this.typeArguments, that.typeArguments) // this part is wrong for punting unless the rhs has no type // arguments, but it's better than a blindfolded pinata swing. else - that.typeArguments.isEmpty && subtype(this.erasure, that.erasure) + that.typeArguments.isEmpty && subtype(this.runtimeClass, that.runtimeClass) } } @@ -90,29 +92,29 @@ trait ClassManifestDeprecatedApis[T] extends OptManifest[T] { @deprecated("Use wrap instead", "2.10.0") def arrayManifest: ClassManifest[Array[T]] = - ClassManifest.classType[Array[T]](arrayClass[T](erasure), this) + ClassManifest.classType[Array[T]](arrayClass[T](runtimeClass), this) override def newArray(len: Int): Array[T] = - java.lang.reflect.Array.newInstance(erasure, len).asInstanceOf[Array[T]] + java.lang.reflect.Array.newInstance(runtimeClass, len).asInstanceOf[Array[T]] @deprecated("Use wrap.newArray instead", "2.10.0") def newArray2(len: Int): Array[Array[T]] = - java.lang.reflect.Array.newInstance(arrayClass[T](erasure), len) + java.lang.reflect.Array.newInstance(arrayClass[T](runtimeClass), len) .asInstanceOf[Array[Array[T]]] @deprecated("Use wrap.wrap.newArray instead", "2.10.0") def newArray3(len: Int): Array[Array[Array[T]]] = - java.lang.reflect.Array.newInstance(arrayClass[Array[T]](arrayClass[T](erasure)), len) + java.lang.reflect.Array.newInstance(arrayClass[Array[T]](arrayClass[T](runtimeClass)), len) .asInstanceOf[Array[Array[Array[T]]]] @deprecated("Use wrap.wrap.wrap.newArray instead", "2.10.0") def newArray4(len: Int): Array[Array[Array[Array[T]]]] = - java.lang.reflect.Array.newInstance(arrayClass[Array[Array[T]]](arrayClass[Array[T]](arrayClass[T](erasure))), len) + java.lang.reflect.Array.newInstance(arrayClass[Array[Array[T]]](arrayClass[Array[T]](arrayClass[T](runtimeClass))), len) .asInstanceOf[Array[Array[Array[Array[T]]]]] @deprecated("Use wrap.wrap.wrap.wrap.newArray instead", "2.10.0") def newArray5(len: Int): Array[Array[Array[Array[Array[T]]]]] = - java.lang.reflect.Array.newInstance(arrayClass[Array[Array[Array[T]]]](arrayClass[Array[Array[T]]](arrayClass[Array[T]](arrayClass[T](erasure)))), len) + java.lang.reflect.Array.newInstance(arrayClass[Array[Array[Array[T]]]](arrayClass[Array[Array[T]]](arrayClass[Array[T]](arrayClass[T](runtimeClass)))), len) .asInstanceOf[Array[Array[Array[Array[Array[T]]]]]] @deprecated("Create WrappedArray directly instead", "2.10.0") @@ -130,7 +132,7 @@ trait ClassManifestDeprecatedApis[T] extends OptManifest[T] { protected def argString = if (typeArguments.nonEmpty) typeArguments.mkString("[", ", ", "]") - else if (erasure.isArray) "["+ClassManifest.fromClass(erasure.getComponentType)+"]" + else if (runtimeClass.isArray) "["+ClassManifest.fromClass(runtimeClass.getComponentType)+"]" else "" } @@ -220,7 +222,7 @@ object ClassManifestFactory { */ def abstractType[T](prefix: OptManifest[_], name: String, upperbound: ClassManifest[_], args: OptManifest[_]*): ClassManifest[T] = new ClassManifest[T] { - override def runtimeClass = upperbound.erasure + override def runtimeClass = upperbound.runtimeClass override val typeArguments = args.toList override def toString = prefix.toString+"#"+name+argString } @@ -235,6 +237,6 @@ private class ClassTypeManifest[T]( { override def toString = (if (prefix.isEmpty) "" else prefix.get.toString+"#") + - (if (erasure.isArray) "Array" else erasure.getName) + + (if (runtimeClass.isArray) "Array" else runtimeClass.getName) + argString }
\ No newline at end of file diff --git a/src/library/scala/reflect/ClassTag.scala b/src/library/scala/reflect/ClassTag.scala index d699e34ffc..33c5cee783 100644 --- a/src/library/scala/reflect/ClassTag.scala +++ b/src/library/scala/reflect/ClassTag.scala @@ -28,7 +28,7 @@ import scala.runtime.ScalaRunTime.{ arrayClass, arrayElementClass } * scala> mkArray("Japan","Brazil","Germany") * res1: Array[String] = Array(Japan, Brazil, Germany) * }}} - * + * * See [[scala.reflect.api.TypeTags]] for more examples, or the * [[http://docs.scala-lang.org/overviews/reflection/typetags-manifests.html Reflection Guide: TypeTags]] * for more details. diff --git a/src/library/scala/reflect/Manifest.scala b/src/library/scala/reflect/Manifest.scala index f62d0ecd16..2f7643bccf 100644 --- a/src/library/scala/reflect/Manifest.scala +++ b/src/library/scala/reflect/Manifest.scala @@ -6,7 +6,8 @@ ** |/ ** \* */ -package scala.reflect +package scala +package reflect import scala.collection.mutable.{ ArrayBuilder, WrappedArray } @@ -45,7 +46,7 @@ trait Manifest[T] extends ClassManifest[T] with Equals { override def typeArguments: List[Manifest[_]] = Nil override def arrayManifest: Manifest[Array[T]] = - Manifest.classType[Array[T]](arrayClass[T](erasure), this) + Manifest.classType[Array[T]](arrayClass[T](runtimeClass), this) override def canEqual(that: Any): Boolean = that match { case _: Manifest[_] => true @@ -55,14 +56,15 @@ trait Manifest[T] extends ClassManifest[T] with Equals { * faster than <:< and rules out most comparisons. */ override def equals(that: Any): Boolean = that match { - case m: Manifest[_] => (m canEqual this) && (this.erasure == m.erasure) && (this <:< m) && (m <:< this) + case m: Manifest[_] => (m canEqual this) && (this.runtimeClass == m.runtimeClass) && (this <:< m) && (m <:< this) case _ => false } - override def hashCode = this.erasure.## + override def hashCode = this.runtimeClass.## } // TODO undeprecated until Scala reflection becomes non-experimental // @deprecated("Use type tags and manually check the corresponding class or type instead", "2.10.0") +@SerialVersionUID(1L) abstract class AnyValManifest[T <: AnyVal](override val toString: String) extends Manifest[T] with Equals { override def <:<(that: ClassManifest[_]): Boolean = (that eq this) || (that eq Manifest.Any) || (that eq Manifest.AnyVal) @@ -71,6 +73,7 @@ abstract class AnyValManifest[T <: AnyVal](override val toString: String) extend case _ => false } override def equals(that: Any): Boolean = this eq that.asInstanceOf[AnyRef] + @transient override val hashCode = System.identityHashCode(this) } @@ -227,6 +230,7 @@ object ManifestFactory { private abstract class PhantomManifest[T](_runtimeClass: Predef.Class[_], override val toString: String) extends ClassTypeManifest[T](None, _runtimeClass, Nil) { override def equals(that: Any): Boolean = this eq that.asInstanceOf[AnyRef] + @transient override val hashCode = System.identityHashCode(this) } @@ -237,7 +241,7 @@ object ManifestFactory { override val typeArguments: List[Manifest[_]]) extends Manifest[T] { override def toString = (if (prefix.isEmpty) "" else prefix.get.toString+"#") + - (if (erasure.isArray) "Array" else erasure.getName) + + (if (runtimeClass.isArray) "Array" else runtimeClass.getName) + argString } @@ -258,7 +262,7 @@ object ManifestFactory { */ def wildcardType[T](lowerBound: Manifest[_], upperBound: Manifest[_]): Manifest[T] = new Manifest[T] { - def runtimeClass = upperBound.erasure + def runtimeClass = upperBound.runtimeClass override def toString = "_" + (if (lowerBound eq Nothing) "" else " >: "+lowerBound) + @@ -268,7 +272,7 @@ object ManifestFactory { /** Manifest for the intersection type `parents_0 with ... with parents_n'. */ def intersectionType[T](parents: Manifest[_]*): Manifest[T] = new Manifest[T] { - def runtimeClass = parents.head.erasure + def runtimeClass = parents.head.runtimeClass override def toString = parents.mkString(" with ") } } diff --git a/src/library/scala/reflect/NameTransformer.scala b/src/library/scala/reflect/NameTransformer.scala index 384ebc6134..a8430548f5 100755 --- a/src/library/scala/reflect/NameTransformer.scala +++ b/src/library/scala/reflect/NameTransformer.scala @@ -15,9 +15,12 @@ package reflect object NameTransformer { // XXX Short term: providing a way to alter these without having to recompile // the compiler before recompiling the compiler. - val MODULE_SUFFIX_STRING = sys.props.getOrElse("SCALA_MODULE_SUFFIX_STRING", "$") - val NAME_JOIN_STRING = sys.props.getOrElse("SCALA_NAME_JOIN_STRING", "$") - val MODULE_INSTANCE_NAME = "MODULE$" + val MODULE_SUFFIX_STRING = sys.props.getOrElse("SCALA_MODULE_SUFFIX_STRING", "$") + val NAME_JOIN_STRING = sys.props.getOrElse("SCALA_NAME_JOIN_STRING", "$") + val MODULE_INSTANCE_NAME = "MODULE$" + val LOCAL_SUFFIX_STRING = " " + val SETTER_SUFFIX_STRING = "_$eq" + val TRAIT_SETTER_SEPARATOR_STRING = "$_setter_$" private val nops = 128 private val ncodes = 26 * 26 @@ -27,9 +30,9 @@ object NameTransformer { private val op2code = new Array[String](nops) private val code2op = new Array[OpCodes](ncodes) private def enterOp(op: Char, code: String) = { - op2code(op) = code + op2code(op.toInt) = code val c = (code.charAt(1) - 'a') * 26 + code.charAt(2) - 'a' - code2op(c) = new OpCodes(op, code, code2op(c)) + code2op(c.toInt) = new OpCodes(op, code, code2op(c)) } /* Note: decoding assumes opcodes are only ever lowercase. */ @@ -63,12 +66,12 @@ object NameTransformer { var i = 0 while (i < len) { val c = name charAt i - if (c < nops && (op2code(c) ne null)) { + if (c < nops && (op2code(c.toInt) ne null)) { if (buf eq null) { buf = new StringBuilder() buf.append(name.substring(0, i)) } - buf.append(op2code(c)) + buf.append(op2code(c.toInt)) /* Handle glyphs that are not valid Java/JVM identifiers */ } else if (!Character.isJavaIdentifierPart(c)) { @@ -93,8 +96,8 @@ object NameTransformer { */ def decode(name0: String): String = { //System.out.println("decode: " + name);//DEBUG - val name = if (name0.endsWith("<init>")) name0.substring(0, name0.length() - ("<init>").length()) + "this" - else name0; + val name = if (name0.endsWith("<init>")) name0.stripSuffix("<init>") + "this" + else name0 var buf: StringBuilder = null val len = name.length() var i = 0 diff --git a/src/library/scala/reflect/NoManifest.scala b/src/library/scala/reflect/NoManifest.scala index 61bc5e28d3..2ef946c80c 100644 --- a/src/library/scala/reflect/NoManifest.scala +++ b/src/library/scala/reflect/NoManifest.scala @@ -6,7 +6,8 @@ ** |/ ** \* */ -package scala.reflect +package scala +package reflect /** One of the branches of an [[scala.reflect.OptManifest]]. */ diff --git a/src/library/scala/reflect/OptManifest.scala b/src/library/scala/reflect/OptManifest.scala index 5e373c7318..b69f55483c 100644 --- a/src/library/scala/reflect/OptManifest.scala +++ b/src/library/scala/reflect/OptManifest.scala @@ -6,7 +6,8 @@ ** |/ ** \* */ -package scala.reflect +package scala +package reflect /** A `OptManifest[T]` is an optional [[scala.reflect.Manifest]]. * diff --git a/src/library/scala/reflect/package.scala b/src/library/scala/reflect/package.scala index 10e6d7d9a4..509d181d87 100644 --- a/src/library/scala/reflect/package.scala +++ b/src/library/scala/reflect/package.scala @@ -1,5 +1,7 @@ package scala +import java.lang.reflect.{ AccessibleObject => jAccessibleObject } + package object reflect { // in the new scheme of things ClassManifests are aliased to ClassTags @@ -42,26 +44,23 @@ package object reflect { def classTag[T](implicit ctag: ClassTag[T]) = ctag + /** Make a java reflection object accessible, if it is not already + * and it is possible to do so. If a SecurityException is thrown in the + * attempt, it is caught and discarded. + */ + def ensureAccessible[T <: jAccessibleObject](m: T): T = { + if (!m.isAccessible) { + try m setAccessible true + catch { case _: SecurityException => } // does nothing + } + m + } + // anchor for the class tag materialization macro emitted during tag materialization in Implicits.scala // implementation is hardwired into `scala.reflect.reify.Taggers` // using the mechanism implemented in `scala.tools.reflect.FastTrack` // todo. once we have implicit macros for tag generation, we can remove this anchor - private[scala] def materializeClassTag[T](): ClassTag[T] = ??? // macro - - @deprecated("Use `@scala.beans.BeanDescription` instead", "2.10.0") - type BeanDescription = scala.beans.BeanDescription - @deprecated("Use `@scala.beans.BeanDisplayName` instead", "2.10.0") - type BeanDisplayName = scala.beans.BeanDisplayName - @deprecated("Use `@scala.beans.BeanInfo` instead", "2.10.0") - type BeanInfo = scala.beans.BeanInfo - @deprecated("Use `@scala.beans.BeanInfoSkip` instead", "2.10.0") - type BeanInfoSkip = scala.beans.BeanInfoSkip - @deprecated("Use `@scala.beans.BeanProperty` instead", "2.10.0") - type BeanProperty = scala.beans.BeanProperty - @deprecated("Use `@scala.beans.BooleanBeanProperty` instead", "2.10.0") - type BooleanBeanProperty = scala.beans.BooleanBeanProperty - @deprecated("Use `@scala.beans.ScalaBeanInfo` instead", "2.10.0") - type ScalaBeanInfo = scala.beans.ScalaBeanInfo + private[scala] def materializeClassTag[T](): ClassTag[T] = macro ??? } /** An exception that indicates an error during Scala reflection */ diff --git a/src/library/scala/runtime/AbstractFunction0.scala b/src/library/scala/runtime/AbstractFunction0.scala index 1b351c62ae..1e677e8008 100644 --- a/src/library/scala/runtime/AbstractFunction0.scala +++ b/src/library/scala/runtime/AbstractFunction0.scala @@ -1,6 +1,6 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** +** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** diff --git a/src/library/scala/runtime/AbstractFunction1.scala b/src/library/scala/runtime/AbstractFunction1.scala index a68a82e6a2..178280cb46 100644 --- a/src/library/scala/runtime/AbstractFunction1.scala +++ b/src/library/scala/runtime/AbstractFunction1.scala @@ -1,6 +1,6 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** +** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** @@ -9,6 +9,6 @@ package scala.runtime -abstract class AbstractFunction1[@specialized(scala.Int, scala.Long, scala.Float, scala.Double/*, scala.AnyRef*/) -T1, @specialized(scala.Unit, scala.Boolean, scala.Int, scala.Float, scala.Long, scala.Double/*, scala.AnyRef*/) +R] extends Function1[T1, R] { +abstract class AbstractFunction1[@specialized(scala.Int, scala.Long, scala.Float, scala.Double) -T1, @specialized(scala.Unit, scala.Boolean, scala.Int, scala.Float, scala.Long, scala.Double) +R] extends Function1[T1, R] { } diff --git a/src/library/scala/runtime/AbstractFunction10.scala b/src/library/scala/runtime/AbstractFunction10.scala index 72c0a2e69d..776f52238d 100644 --- a/src/library/scala/runtime/AbstractFunction10.scala +++ b/src/library/scala/runtime/AbstractFunction10.scala @@ -1,6 +1,6 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** +** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** diff --git a/src/library/scala/runtime/AbstractFunction11.scala b/src/library/scala/runtime/AbstractFunction11.scala index 031f3044a1..76cd8fbb3c 100644 --- a/src/library/scala/runtime/AbstractFunction11.scala +++ b/src/library/scala/runtime/AbstractFunction11.scala @@ -1,6 +1,6 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** +** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** diff --git a/src/library/scala/runtime/AbstractFunction12.scala b/src/library/scala/runtime/AbstractFunction12.scala index 9823edbc60..10066ed4b3 100644 --- a/src/library/scala/runtime/AbstractFunction12.scala +++ b/src/library/scala/runtime/AbstractFunction12.scala @@ -1,6 +1,6 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** +** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** diff --git a/src/library/scala/runtime/AbstractFunction13.scala b/src/library/scala/runtime/AbstractFunction13.scala index 528719b216..6c3a45734c 100644 --- a/src/library/scala/runtime/AbstractFunction13.scala +++ b/src/library/scala/runtime/AbstractFunction13.scala @@ -1,6 +1,6 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** +** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** diff --git a/src/library/scala/runtime/AbstractFunction14.scala b/src/library/scala/runtime/AbstractFunction14.scala index ecae45a107..bf2b6736f4 100644 --- a/src/library/scala/runtime/AbstractFunction14.scala +++ b/src/library/scala/runtime/AbstractFunction14.scala @@ -1,6 +1,6 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** +** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** diff --git a/src/library/scala/runtime/AbstractFunction15.scala b/src/library/scala/runtime/AbstractFunction15.scala index 5f5e8afcf7..5136f666c8 100644 --- a/src/library/scala/runtime/AbstractFunction15.scala +++ b/src/library/scala/runtime/AbstractFunction15.scala @@ -1,6 +1,6 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** +** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** diff --git a/src/library/scala/runtime/AbstractFunction16.scala b/src/library/scala/runtime/AbstractFunction16.scala index c0093c4fbb..dbafab8301 100644 --- a/src/library/scala/runtime/AbstractFunction16.scala +++ b/src/library/scala/runtime/AbstractFunction16.scala @@ -1,6 +1,6 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** +** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** diff --git a/src/library/scala/runtime/AbstractFunction17.scala b/src/library/scala/runtime/AbstractFunction17.scala index caae343a79..9c36dbf5d8 100644 --- a/src/library/scala/runtime/AbstractFunction17.scala +++ b/src/library/scala/runtime/AbstractFunction17.scala @@ -1,6 +1,6 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** +** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** diff --git a/src/library/scala/runtime/AbstractFunction18.scala b/src/library/scala/runtime/AbstractFunction18.scala index 9a2bdffee1..30eee9586f 100644 --- a/src/library/scala/runtime/AbstractFunction18.scala +++ b/src/library/scala/runtime/AbstractFunction18.scala @@ -1,6 +1,6 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** +** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** diff --git a/src/library/scala/runtime/AbstractFunction19.scala b/src/library/scala/runtime/AbstractFunction19.scala index 1dbbd61004..14baf5f1eb 100644 --- a/src/library/scala/runtime/AbstractFunction19.scala +++ b/src/library/scala/runtime/AbstractFunction19.scala @@ -1,6 +1,6 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** +** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** diff --git a/src/library/scala/runtime/AbstractFunction2.scala b/src/library/scala/runtime/AbstractFunction2.scala index 0905ea178c..223ade9983 100644 --- a/src/library/scala/runtime/AbstractFunction2.scala +++ b/src/library/scala/runtime/AbstractFunction2.scala @@ -1,6 +1,6 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** +** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** diff --git a/src/library/scala/runtime/AbstractFunction20.scala b/src/library/scala/runtime/AbstractFunction20.scala index eb4c085427..f5c29571bf 100644 --- a/src/library/scala/runtime/AbstractFunction20.scala +++ b/src/library/scala/runtime/AbstractFunction20.scala @@ -1,6 +1,6 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** +** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** diff --git a/src/library/scala/runtime/AbstractFunction21.scala b/src/library/scala/runtime/AbstractFunction21.scala index 98e32b22f1..15feea3a66 100644 --- a/src/library/scala/runtime/AbstractFunction21.scala +++ b/src/library/scala/runtime/AbstractFunction21.scala @@ -1,6 +1,6 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** +** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** diff --git a/src/library/scala/runtime/AbstractFunction22.scala b/src/library/scala/runtime/AbstractFunction22.scala index 67b13399d1..d77369ff01 100644 --- a/src/library/scala/runtime/AbstractFunction22.scala +++ b/src/library/scala/runtime/AbstractFunction22.scala @@ -1,6 +1,6 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** +** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** diff --git a/src/library/scala/runtime/AbstractFunction3.scala b/src/library/scala/runtime/AbstractFunction3.scala index 3a45cdcea5..f863509214 100644 --- a/src/library/scala/runtime/AbstractFunction3.scala +++ b/src/library/scala/runtime/AbstractFunction3.scala @@ -1,6 +1,6 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** +** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** diff --git a/src/library/scala/runtime/AbstractFunction4.scala b/src/library/scala/runtime/AbstractFunction4.scala index fbf55344f6..5927015ef8 100644 --- a/src/library/scala/runtime/AbstractFunction4.scala +++ b/src/library/scala/runtime/AbstractFunction4.scala @@ -1,6 +1,6 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** +** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** diff --git a/src/library/scala/runtime/AbstractFunction5.scala b/src/library/scala/runtime/AbstractFunction5.scala index 949bae8ab7..411e1e14bf 100644 --- a/src/library/scala/runtime/AbstractFunction5.scala +++ b/src/library/scala/runtime/AbstractFunction5.scala @@ -1,6 +1,6 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** +** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** diff --git a/src/library/scala/runtime/AbstractFunction6.scala b/src/library/scala/runtime/AbstractFunction6.scala index 337fd9f3fc..411c30d480 100644 --- a/src/library/scala/runtime/AbstractFunction6.scala +++ b/src/library/scala/runtime/AbstractFunction6.scala @@ -1,6 +1,6 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** +** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** diff --git a/src/library/scala/runtime/AbstractFunction7.scala b/src/library/scala/runtime/AbstractFunction7.scala index 24458678ad..498f98633a 100644 --- a/src/library/scala/runtime/AbstractFunction7.scala +++ b/src/library/scala/runtime/AbstractFunction7.scala @@ -1,6 +1,6 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** +** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** diff --git a/src/library/scala/runtime/AbstractFunction8.scala b/src/library/scala/runtime/AbstractFunction8.scala index 6d3dac849e..c6d320b887 100644 --- a/src/library/scala/runtime/AbstractFunction8.scala +++ b/src/library/scala/runtime/AbstractFunction8.scala @@ -1,6 +1,6 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** +** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** diff --git a/src/library/scala/runtime/AbstractFunction9.scala b/src/library/scala/runtime/AbstractFunction9.scala index 43cf3d2a74..34bd9d7107 100644 --- a/src/library/scala/runtime/AbstractFunction9.scala +++ b/src/library/scala/runtime/AbstractFunction9.scala @@ -1,6 +1,6 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** +** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** diff --git a/src/library/scala/runtime/AbstractPartialFunction.scala b/src/library/scala/runtime/AbstractPartialFunction.scala index 57f8e2603b..986cd0390f 100644 --- a/src/library/scala/runtime/AbstractPartialFunction.scala +++ b/src/library/scala/runtime/AbstractPartialFunction.scala @@ -6,7 +6,10 @@ ** |/ ** \* */ -package scala.runtime +package scala +package runtime + +import scala.annotation.unspecialized /** `AbstractPartialFunction` reformulates all operations of its supertrait `PartialFunction` * in terms of `isDefinedAt` and `applyOrElse`. @@ -22,7 +25,7 @@ package scala.runtime * @author Pavel Pavlov * @since 2.10 */ -abstract class AbstractPartialFunction[@specialized(scala.Int, scala.Long, scala.Float, scala.Double, scala.AnyRef) -T1, @specialized(scala.Unit, scala.Boolean, scala.Int, scala.Float, scala.Long, scala.Double, scala.AnyRef) +R] extends Function1[T1, R] with PartialFunction[T1, R] { self => +abstract class AbstractPartialFunction[@specialized(scala.Int, scala.Long, scala.Float, scala.Double) -T1, @specialized(scala.Unit, scala.Boolean, scala.Int, scala.Float, scala.Long, scala.Double) +R] extends Function1[T1, R] with PartialFunction[T1, R] { self => // this method must be overridden for better performance, // for backwards compatibility, fall back to the one inherited from PartialFunction // this assumes the old-school partial functions override the apply method, though diff --git a/src/library/scala/runtime/BooleanRef.java b/src/library/scala/runtime/BooleanRef.java index 889db31e2a..92e8055351 100644 --- a/src/library/scala/runtime/BooleanRef.java +++ b/src/library/scala/runtime/BooleanRef.java @@ -17,4 +17,7 @@ public class BooleanRef implements java.io.Serializable { public boolean elem; public BooleanRef(boolean elem) { this.elem = elem; } public String toString() { return String.valueOf(elem); } + + public static BooleanRef create(boolean e) { return new BooleanRef(e); } + public static BooleanRef zero() { return new BooleanRef(false); } } diff --git a/src/library/scala/runtime/Boxed.scala b/src/library/scala/runtime/Boxed.scala index 8b531076ac..933444773d 100644 --- a/src/library/scala/runtime/Boxed.scala +++ b/src/library/scala/runtime/Boxed.scala @@ -6,12 +6,7 @@ ** |/ ** \* */ +package scala +package runtime - -package scala.runtime - -trait Boxed { - -} - - +trait Boxed { } diff --git a/src/library/scala/runtime/BoxesRunTime.java b/src/library/scala/runtime/BoxesRunTime.java index 3504c57b48..82a3b00ac4 100644 --- a/src/library/scala/runtime/BoxesRunTime.java +++ b/src/library/scala/runtime/BoxesRunTime.java @@ -10,7 +10,6 @@ package scala.runtime; -import java.io.*; import scala.math.ScalaNumber; /** An object (static class) that defines methods used for creating, diff --git a/src/library/scala/runtime/ByteRef.java b/src/library/scala/runtime/ByteRef.java index cc10611e26..27d3259db3 100644 --- a/src/library/scala/runtime/ByteRef.java +++ b/src/library/scala/runtime/ByteRef.java @@ -17,4 +17,7 @@ public class ByteRef implements java.io.Serializable { public byte elem; public ByteRef(byte elem) { this.elem = elem; } public String toString() { return java.lang.Byte.toString(elem); } + + public static ByteRef create(byte e) { return new ByteRef(e); } + public static ByteRef zero() { return new ByteRef((byte)0); } } diff --git a/src/library/scala/runtime/CharRef.java b/src/library/scala/runtime/CharRef.java index 03d3337b3d..31956f5b55 100644 --- a/src/library/scala/runtime/CharRef.java +++ b/src/library/scala/runtime/CharRef.java @@ -17,4 +17,7 @@ public class CharRef implements java.io.Serializable { public char elem; public CharRef(char elem) { this.elem = elem; } public String toString() { return java.lang.Character.toString(elem); } + + public static CharRef create(char e) { return new CharRef(e); } + public static CharRef zero() { return new CharRef((char)0); } } diff --git a/src/library/scala/runtime/DoubleRef.java b/src/library/scala/runtime/DoubleRef.java index 317198ee48..0c7d9156d6 100644 --- a/src/library/scala/runtime/DoubleRef.java +++ b/src/library/scala/runtime/DoubleRef.java @@ -17,4 +17,7 @@ public class DoubleRef implements java.io.Serializable { public double elem; public DoubleRef(double elem) { this.elem = elem; } public String toString() { return java.lang.Double.toString(elem); } + + public static DoubleRef create(double e) { return new DoubleRef(e); } + public static DoubleRef zero() { return new DoubleRef(0); } } diff --git a/src/library/scala/runtime/FloatRef.java b/src/library/scala/runtime/FloatRef.java index e26b89be60..f0e1d5f8f3 100644 --- a/src/library/scala/runtime/FloatRef.java +++ b/src/library/scala/runtime/FloatRef.java @@ -17,4 +17,7 @@ public class FloatRef implements java.io.Serializable { public float elem; public FloatRef(float elem) { this.elem = elem; } public String toString() { return java.lang.Float.toString(elem); } + + public static FloatRef create(float e) { return new FloatRef(e); } + public static FloatRef zero() { return new FloatRef(0); } } diff --git a/src/library/scala/runtime/IntRef.java b/src/library/scala/runtime/IntRef.java index edb6fafe94..adcf474aae 100644 --- a/src/library/scala/runtime/IntRef.java +++ b/src/library/scala/runtime/IntRef.java @@ -17,4 +17,7 @@ public class IntRef implements java.io.Serializable { public int elem; public IntRef(int elem) { this.elem = elem; } public String toString() { return java.lang.Integer.toString(elem); } + + public static IntRef create(int e) { return new IntRef(e); } + public static IntRef zero() { return new IntRef(0); } } diff --git a/src/library/scala/runtime/LongRef.java b/src/library/scala/runtime/LongRef.java index 12004b5bb5..51426ab8f6 100644 --- a/src/library/scala/runtime/LongRef.java +++ b/src/library/scala/runtime/LongRef.java @@ -17,4 +17,7 @@ public class LongRef implements java.io.Serializable { public long elem; public LongRef(long elem) { this.elem = elem; } public String toString() { return java.lang.Long.toString(elem); } + + public static LongRef create(long e) { return new LongRef(e); } + public static LongRef zero() { return new LongRef(0); } } diff --git a/src/library/scala/runtime/MethodCache.scala b/src/library/scala/runtime/MethodCache.scala index 217b51893b..2d5f832e1f 100644 --- a/src/library/scala/runtime/MethodCache.scala +++ b/src/library/scala/runtime/MethodCache.scala @@ -6,7 +6,9 @@ ** |/ ** \* */ -package scala.runtime +package scala +package runtime + import java.lang.reflect.{ Method => JMethod } import java.lang.{ Class => JClass } @@ -20,7 +22,7 @@ import scala.annotation.tailrec * generated per call point, and will uniquely relate to the method called * at that point, making the method name and argument types irrelevant. */ /* TODO: if performance is acceptable, PolyMethodCache should be made generic on the method type */ -sealed abstract class MethodCache { +private[scala] sealed abstract class MethodCache { /** Searches for a cached method in the `MethodCache` chain that * is compatible with receiver class `forReceiver`. If none is cached, * `null` is returned. If `null` is returned, find's caller should look- @@ -30,7 +32,7 @@ sealed abstract class MethodCache { def add(forReceiver: JClass[_], forMethod: JMethod): MethodCache } -final class EmptyMethodCache extends MethodCache { +private[scala] final class EmptyMethodCache extends MethodCache { def find(forReceiver: JClass[_]): JMethod = null @@ -39,7 +41,7 @@ final class EmptyMethodCache extends MethodCache { } -final class MegaMethodCache( +private[scala] final class MegaMethodCache( private[this] val forName: String, private[this] val forParameterTypes: Array[JClass[_]] ) extends MethodCache { @@ -51,7 +53,7 @@ final class MegaMethodCache( } -final class PolyMethodCache( +private[scala] final class PolyMethodCache( private[this] val next: MethodCache, private[this] val receiver: JClass[_], private[this] val method: JMethod, diff --git a/src/library/scala/runtime/NonLocalReturnControl.scala b/src/library/scala/runtime/NonLocalReturnControl.scala index b9525ef419..a926956acf 100644 --- a/src/library/scala/runtime/NonLocalReturnControl.scala +++ b/src/library/scala/runtime/NonLocalReturnControl.scala @@ -6,7 +6,8 @@ ** |/ ** \* */ -package scala.runtime +package scala +package runtime import scala.util.control.ControlThrowable diff --git a/src/library/scala/runtime/Nothing$.scala b/src/library/scala/runtime/Nothing$.scala index 04fcc55a1c..4ecc536223 100644 --- a/src/library/scala/runtime/Nothing$.scala +++ b/src/library/scala/runtime/Nothing$.scala @@ -6,7 +6,9 @@ ** |/ ** \* */ -package scala.runtime +package scala +package runtime + /** * Dummy class which exist only to satisfy the JVM. It corresponds diff --git a/src/library/scala/runtime/Null$.scala b/src/library/scala/runtime/Null$.scala index 797b31583d..87ce0a2498 100644 --- a/src/library/scala/runtime/Null$.scala +++ b/src/library/scala/runtime/Null$.scala @@ -6,11 +6,13 @@ ** |/ ** \* */ -package scala.runtime +package scala +package runtime /** * Dummy class which exist only to satisfy the JVM. It corresponds to * `scala.Null`. If such type appears in method signatures, it is erased - * to this one. + * to this one. A private constructor ensures that Java code can't create + * subclasses. The only value of type Null$ should be null */ -sealed abstract class Null$ +sealed abstract class Null$ private () diff --git a/src/library/scala/runtime/ObjectRef.java b/src/library/scala/runtime/ObjectRef.java index c8298b8b21..b34f81c9c8 100644 --- a/src/library/scala/runtime/ObjectRef.java +++ b/src/library/scala/runtime/ObjectRef.java @@ -16,5 +16,9 @@ public class ObjectRef<T> implements java.io.Serializable { public T elem; public ObjectRef(T elem) { this.elem = elem; } + @Override public String toString() { return String.valueOf(elem); } + + public static <U> ObjectRef<U> create(U e) { return new ObjectRef<U>(e); } + public static ObjectRef<Object> zero() { return new ObjectRef<Object>(null); } } diff --git a/src/library/scala/runtime/RichBoolean.scala b/src/library/scala/runtime/RichBoolean.scala index 97e2b77f96..4f867960a0 100644 --- a/src/library/scala/runtime/RichBoolean.scala +++ b/src/library/scala/runtime/RichBoolean.scala @@ -6,7 +6,9 @@ ** |/ ** \* */ -package scala.runtime +package scala +package runtime + final class RichBoolean(val self: Boolean) extends AnyVal with OrderedProxy[Boolean] { protected def ord = scala.math.Ordering.Boolean diff --git a/src/library/scala/runtime/RichByte.scala b/src/library/scala/runtime/RichByte.scala index ca578620cf..ce658d2277 100644 --- a/src/library/scala/runtime/RichByte.scala +++ b/src/library/scala/runtime/RichByte.scala @@ -6,9 +6,25 @@ ** |/ ** \* */ -package scala.runtime +package scala +package runtime + final class RichByte(val self: Byte) extends AnyVal with ScalaWholeNumberProxy[Byte] { protected def num = scala.math.Numeric.ByteIsIntegral protected def ord = scala.math.Ordering.Byte + + override def doubleValue() = self.toDouble + override def floatValue() = self.toFloat + override def longValue() = self.toLong + override def intValue() = self.toInt + override def byteValue() = self + override def shortValue() = self.toShort + + override def isValidByte = true + + override def abs: Byte = math.abs(self).toByte + override def max(that: Byte): Byte = math.max(self, that).toByte + override def min(that: Byte): Byte = math.min(self, that).toByte + override def signum: Int = math.signum(self.toInt) } diff --git a/src/library/scala/runtime/RichChar.scala b/src/library/scala/runtime/RichChar.scala index 5124ca00de..71ea3a21e1 100644 --- a/src/library/scala/runtime/RichChar.scala +++ b/src/library/scala/runtime/RichChar.scala @@ -6,7 +6,9 @@ ** |/ ** \* */ -package scala.runtime +package scala +package runtime + import java.lang.Character @@ -14,6 +16,20 @@ final class RichChar(val self: Char) extends AnyVal with IntegralProxy[Char] { protected def num = scala.math.Numeric.CharIsIntegral protected def ord = scala.math.Ordering.Char + override def doubleValue() = self.toDouble + override def floatValue() = self.toFloat + override def longValue() = self.toLong + override def intValue() = self.toInt + override def byteValue() = self.toByte + override def shortValue() = self.toShort + + override def isValidChar = true + + override def abs: Char = self + override def max(that: Char): Char = math.max(self.toInt, that.toInt).toChar + override def min(that: Char): Char = math.min(self.toInt, that.toInt).toChar + override def signum: Int = math.signum(self.toInt) + def asDigit: Int = Character.digit(self, Character.MAX_RADIX) def isControl: Boolean = Character.isISOControl(self) diff --git a/src/library/scala/runtime/RichDouble.scala b/src/library/scala/runtime/RichDouble.scala index 2f16a296b3..9d7a55d5cd 100644 --- a/src/library/scala/runtime/RichDouble.scala +++ b/src/library/scala/runtime/RichDouble.scala @@ -14,6 +14,35 @@ final class RichDouble(val self: Double) extends AnyVal with FractionalProxy[Dou protected def ord = scala.math.Ordering.Double protected def integralNum = scala.math.Numeric.DoubleAsIfIntegral + override def doubleValue() = self + override def floatValue() = self.toFloat + override def longValue() = self.toLong + override def intValue() = self.toInt + override def byteValue() = self.toByte + override def shortValue() = self.toShort + + override def isWhole = { + val l = self.toLong + l.toDouble == self || l == Long.MaxValue && self < Double.PositiveInfinity || l == Long.MinValue && self > Double.NegativeInfinity + } + override def isValidByte = self.toByte.toDouble == self + override def isValidShort = self.toShort.toDouble == self + override def isValidChar = self.toChar.toDouble == self + override def isValidInt = self.toInt.toDouble == self + // override def isValidLong = { val l = self.toLong; l.toDouble == self && l != Long.MaxValue } + // override def isValidFloat = self.toFloat.toDouble == self + // override def isValidDouble = !java.lang.Double.isNaN(self) + + def isNaN: Boolean = java.lang.Double.isNaN(self) + def isInfinity: Boolean = java.lang.Double.isInfinite(self) + def isPosInfinity: Boolean = Double.PositiveInfinity == self + def isNegInfinity: Boolean = Double.NegativeInfinity == self + + override def abs: Double = math.abs(self) + override def max(that: Double): Double = math.max(self, that) + override def min(that: Double): Double = math.min(self, that) + override def signum: Int = math.signum(self).toInt // !!! NaN + def round: Long = math.round(self) def ceil: Double = math.ceil(self) def floor: Double = math.floor(self) @@ -30,22 +59,4 @@ final class RichDouble(val self: Double) extends AnyVal with FractionalProxy[Dou * @return the measurement of the angle x in degrees. */ def toDegrees: Double = math.toDegrees(self) - - // isNaN is provided by the implicit conversion to java.lang.Double - // def isNaN: Boolean = java.lang.Double.isNaN(self) - def isInfinity: Boolean = java.lang.Double.isInfinite(self) - def isPosInfinity: Boolean = isInfinity && self > 0.0 - def isNegInfinity: Boolean = isInfinity && self < 0.0 - - override def isValidByte = self.toByte.toDouble == self - override def isValidShort = self.toShort.toDouble == self - override def isValidChar = self.toChar.toDouble == self - override def isValidInt = self.toInt.toDouble == self - // override def isValidLong = { val l = self.toLong; l.toDouble == self && l != Long.MaxValue } - // override def isValidFloat = self.toFloat.toDouble == self - // override def isValidDouble = !java.lang.Double.isNaN(self) - override def isWhole = { - val l = self.toLong - l.toDouble == self || l == Long.MaxValue && self < Double.PositiveInfinity || l == Long.MinValue && self > Double.NegativeInfinity - } } diff --git a/src/library/scala/runtime/RichException.scala b/src/library/scala/runtime/RichException.scala index 94c4137674..f01788a4e9 100644 --- a/src/library/scala/runtime/RichException.scala +++ b/src/library/scala/runtime/RichException.scala @@ -6,10 +6,12 @@ ** |/ ** \* */ -package scala.runtime +package scala +package runtime import scala.compat.Platform.EOL +@deprecated("Use Throwable#getStackTrace", "2.11.0") final class RichException(exc: Throwable) { def getStackTraceString = exc.getStackTrace().mkString("", EOL, EOL) } diff --git a/src/library/scala/runtime/RichFloat.scala b/src/library/scala/runtime/RichFloat.scala index cb0681bc19..93777f2405 100644 --- a/src/library/scala/runtime/RichFloat.scala +++ b/src/library/scala/runtime/RichFloat.scala @@ -14,39 +14,50 @@ final class RichFloat(val self: Float) extends AnyVal with FractionalProxy[Float protected def ord = scala.math.Ordering.Float protected def integralNum = scala.math.Numeric.FloatAsIfIntegral + override def doubleValue() = self.toDouble + override def floatValue() = self + override def longValue() = self.toLong + override def intValue() = self.toInt + override def byteValue() = self.toByte + override def shortValue() = self.toShort + + override def isWhole = { + val l = self.toLong + l.toFloat == self || l == Long.MaxValue && self < Float.PositiveInfinity || l == Long.MinValue && self > Float.NegativeInfinity + } + override def isValidByte = self.toByte.toFloat == self + override def isValidShort = self.toShort.toFloat == self + override def isValidChar = self.toChar.toFloat == self + override def isValidInt = { val i = self.toInt; i.toFloat == self && i != Int.MaxValue } + // override def isValidLong = { val l = self.toLong; l.toFloat == self && l != Long.MaxValue } + // override def isValidFloat = !java.lang.Float.isNaN(self) + // override def isValidDouble = !java.lang.Float.isNaN(self) + + def isNaN: Boolean = java.lang.Float.isNaN(self) + def isInfinity: Boolean = java.lang.Float.isInfinite(self) + def isPosInfinity: Boolean = Float.PositiveInfinity == self + def isNegInfinity: Boolean = Float.NegativeInfinity == self + + override def abs: Float = math.abs(self) + override def max(that: Float): Float = math.max(self, that) + override def min(that: Float): Float = math.min(self, that) + override def signum: Int = math.signum(self).toInt // !!! NaN + def round: Int = math.round(self) - def ceil: Float = math.ceil(self).toFloat - def floor: Float = math.floor(self).toFloat + def ceil: Float = math.ceil(self.toDouble).toFloat + def floor: Float = math.floor(self.toDouble).toFloat /** Converts an angle measured in degrees to an approximately equivalent * angle measured in radians. * * @return the measurement of the angle `x` in radians. */ - def toRadians: Float = math.toRadians(self).toFloat + def toRadians: Float = math.toRadians(self.toDouble).toFloat /** Converts an angle measured in radians to an approximately equivalent * angle measured in degrees. * * @return the measurement of the angle `x` in degrees. */ - def toDegrees: Float = math.toDegrees(self).toFloat - - // isNaN is provided by the implicit conversion to java.lang.Float - // def isNaN: Boolean = java.lang.Float.isNaN(self) - def isInfinity: Boolean = java.lang.Float.isInfinite(self) - def isPosInfinity: Boolean = isInfinity && self > 0.0f - def isNegInfinity: Boolean = isInfinity && self < 0.0f - - override def isValidByte = self.toByte.toFloat == self - override def isValidShort = self.toShort.toFloat == self - override def isValidChar = self.toChar.toFloat == self - override def isValidInt = { val i = self.toInt; i.toFloat == self && i != Int.MaxValue } - // override def isValidLong = { val l = self.toLong; l.toFloat == self && l != Long.MaxValue } - // override def isValidFloat = !java.lang.Float.isNaN(self) - // override def isValidDouble = !java.lang.Float.isNaN(self) - override def isWhole = { - val l = self.toLong - l.toFloat == self || l == Long.MaxValue && self < Float.PositiveInfinity || l == Long.MinValue && self > Float.NegativeInfinity - } + def toDegrees: Float = math.toDegrees(self.toDouble).toFloat } diff --git a/src/library/scala/runtime/RichInt.scala b/src/library/scala/runtime/RichInt.scala index 192f94f939..cda9d2907a 100644 --- a/src/library/scala/runtime/RichInt.scala +++ b/src/library/scala/runtime/RichInt.scala @@ -6,7 +6,8 @@ ** |/ ** \* */ -package scala.runtime +package scala +package runtime import scala.collection.immutable.Range @@ -15,14 +16,37 @@ import scala.collection.immutable.Range final class RichInt(val self: Int) extends AnyVal with ScalaNumberProxy[Int] with RangedProxy[Int] { protected def num = scala.math.Numeric.IntIsIntegral protected def ord = scala.math.Ordering.Int - type ResultWithoutStep = Range - /** - * @return `'''true'''` if this number has no decimal component. - * Always returns `'''true'''` for `RichInt`. + override def doubleValue() = self.toDouble + override def floatValue() = self.toFloat + override def longValue() = self.toLong + override def intValue() = self + override def byteValue() = self.toByte + override def shortValue() = self.toShort + + /** Returns `'''true'''` if this number has no decimal component. + * Always `'''true'''` for `RichInt`. */ def isWhole() = true + override def isValidInt = true + def isValidLong = true + + override def abs: Int = math.abs(self) + override def max(that: Int): Int = math.max(self, that) + override def min(that: Int): Int = math.min(self, that) + override def signum: Int = math.signum(self) + + /** There is no reason to round an `Int`, but this method is provided to avoid accidental loss of precision from a detour through `Float`. */ + @deprecated("This is an integer type; there is no reason to round it. Perhaps you meant to call this on a floating-point value?", "2.11.0") + def round: Int = self + + def toBinaryString: String = java.lang.Integer.toBinaryString(self) + def toHexString: String = java.lang.Integer.toHexString(self) + def toOctalString: String = java.lang.Integer.toOctalString(self) + + type ResultWithoutStep = Range + /** * @param end The final bound of the range to make. * @return A [[scala.collection.immutable.Range]] from `this` up to but @@ -53,23 +77,4 @@ final class RichInt(val self: Int) extends AnyVal with ScalaNumberProxy[Int] wit * and including `end`. */ def to(end: Int, step: Int): Range.Inclusive = Range.inclusive(self, end, step) - - /** - * @return `'''this'''` if `'''this''' < that` or `that` otherwise - */ - override def min(that: Int): Int = if (self < that) self else that - - /** - * @return `'''this'''` if `'''this''' > that` or `that` otherwise - */ - override def max(that: Int): Int = if (self > that) self else that - - /** - * Computes the absolute value of `'''this'''`. - */ - override def abs: Int = if (self < 0) -self else self - - def toBinaryString: String = java.lang.Integer.toBinaryString(self) - def toHexString: String = java.lang.Integer.toHexString(self) - def toOctalString: String = java.lang.Integer.toOctalString(self) } diff --git a/src/library/scala/runtime/RichLong.scala b/src/library/scala/runtime/RichLong.scala index ce2d1fdcbd..b405fcda3d 100644 --- a/src/library/scala/runtime/RichLong.scala +++ b/src/library/scala/runtime/RichLong.scala @@ -6,21 +6,38 @@ ** |/ ** \* */ -package scala.runtime +package scala +package runtime final class RichLong(val self: Long) extends AnyVal with IntegralProxy[Long] { protected def num = scala.math.Numeric.LongIsIntegral protected def ord = scala.math.Ordering.Long - def toBinaryString: String = java.lang.Long.toBinaryString(self) - def toHexString: String = java.lang.Long.toHexString(self) - def toOctalString: String = java.lang.Long.toOctalString(self) + override def doubleValue() = self.toDouble + override def floatValue() = self.toFloat + override def longValue() = self + override def intValue() = self.toInt + override def byteValue() = self.toByte + override def shortValue() = self.toShort - override def isValidByte = self.toByte.toLong == self + override def isValidByte = self.toByte.toLong == self override def isValidShort = self.toShort.toLong == self - override def isValidChar = self.toChar.toLong == self - override def isValidInt = self.toInt.toLong == self - // override def isValidLong = true + override def isValidChar = self.toChar.toLong == self + override def isValidInt = self.toInt.toLong == self + def isValidLong = true // override def isValidFloat = self.toFloat.toLong == self && self != Long.MaxValue // override def isValidDouble = self.toDouble.toLong == self && self != Long.MaxValue + + override def abs: Long = math.abs(self) + override def max(that: Long): Long = math.max(self, that) + override def min(that: Long): Long = math.min(self, that) + override def signum: Int = math.signum(self).toInt + + /** There is no reason to round a `Long`, but this method is provided to avoid accidental conversion to `Int` through `Float`. */ + @deprecated("This is an integer type; there is no reason to round it. Perhaps you meant to call this on a floating-point value?", "2.11.0") + def round: Long = self + + def toBinaryString: String = java.lang.Long.toBinaryString(self) + def toHexString: String = java.lang.Long.toHexString(self) + def toOctalString: String = java.lang.Long.toOctalString(self) } diff --git a/src/library/scala/runtime/RichShort.scala b/src/library/scala/runtime/RichShort.scala index aa24dd2ba6..b35beff7eb 100644 --- a/src/library/scala/runtime/RichShort.scala +++ b/src/library/scala/runtime/RichShort.scala @@ -6,9 +6,25 @@ ** |/ ** \* */ -package scala.runtime +package scala +package runtime + final class RichShort(val self: Short) extends AnyVal with ScalaWholeNumberProxy[Short] { protected def num = scala.math.Numeric.ShortIsIntegral protected def ord = scala.math.Ordering.Short + + override def doubleValue() = self.toDouble + override def floatValue() = self.toFloat + override def longValue() = self.toLong + override def intValue() = self.toInt + override def byteValue() = self.toByte + override def shortValue() = self + + override def isValidShort = true + + override def abs: Short = math.abs(self.toInt).toShort + override def max(that: Short): Short = math.max(self.toInt, that.toInt).toShort + override def min(that: Short): Short = math.min(self.toInt, that.toInt).toShort + override def signum: Int = math.signum(self.toInt) } diff --git a/src/library/scala/runtime/ScalaNumberProxy.scala b/src/library/scala/runtime/ScalaNumberProxy.scala index 76fc38b267..5e4da24c0d 100644 --- a/src/library/scala/runtime/ScalaNumberProxy.scala +++ b/src/library/scala/runtime/ScalaNumberProxy.scala @@ -6,7 +6,8 @@ ** |/ ** \* */ -package scala.runtime +package scala +package runtime import scala.collection.{ mutable, immutable } import scala.math.{ ScalaNumericConversions, ScalaNumericAnyConversions } @@ -28,12 +29,16 @@ trait ScalaNumberProxy[T] extends Any with ScalaNumericAnyConversions with Typed def floatValue() = num.toFloat(self) def longValue() = num.toLong(self) def intValue() = num.toInt(self) - def byteValue() = intValue.toByte - def shortValue() = intValue.toShort + def byteValue() = intValue().toByte + def shortValue() = intValue().toShort + /** Returns `'''this'''` if `'''this''' < that` or `that` otherwise. */ def min(that: T): T = num.min(self, that) + /** Returns `'''this'''` if `'''this''' > that` or `that` otherwise. */ def max(that: T): T = num.max(self, that) + /** Returns the absolute value of `'''this'''`. */ def abs = num.abs(self) + /** Returns the signum of `'''this'''`. */ def signum = num.signum(self) } trait ScalaWholeNumberProxy[T] extends Any with ScalaNumberProxy[T] { diff --git a/src/library/scala/runtime/ScalaRunTime.scala b/src/library/scala/runtime/ScalaRunTime.scala index dcd323961e..5fb24f2a36 100644 --- a/src/library/scala/runtime/ScalaRunTime.scala +++ b/src/library/scala/runtime/ScalaRunTime.scala @@ -12,10 +12,9 @@ package runtime import scala.collection.{ Seq, IndexedSeq, TraversableView, AbstractIterator } import scala.collection.mutable.WrappedArray import scala.collection.immutable.{ StringLike, NumericRange, List, Stream, Nil, :: } -import scala.collection.generic.{ Sorted } +import scala.collection.generic.{ Sorted, IsTraversableLike } import scala.reflect.{ ClassTag, classTag } import scala.util.control.ControlThrowable -import scala.xml.{ Node, MetaData } import java.lang.{ Class => jClass } import java.lang.Double.doubleToLongBits @@ -26,8 +25,7 @@ import java.lang.reflect.{ Modifier, Method => JMethod } * outside the API and subject to change or removal without notice. */ object ScalaRunTime { - def isArray(x: AnyRef): Boolean = isArray(x, 1) - def isArray(x: Any, atLevel: Int): Boolean = + def isArray(x: Any, atLevel: Int = 1): Boolean = x != null && isArrayClass(x.getClass, atLevel) private def isArrayClass(clazz: jClass[_], atLevel: Int): Boolean = @@ -42,6 +40,10 @@ object ScalaRunTime { case _ => false } + // A helper method to make my life in the pattern matcher a lot easier. + def drop[Repr](coll: Repr, num: Int)(implicit traversable: IsTraversableLike[Repr]): Repr = + traversable conversion coll drop num + /** Return the class object representing an array with element class `clazz`. */ def arrayClass(clazz: jClass[_]): jClass[_] = { @@ -155,13 +157,7 @@ object ScalaRunTime { // Java bug: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4071957 // More background at ticket #2318. - def ensureAccessible(m: JMethod): JMethod = { - if (!m.isAccessible) { - try m setAccessible true - catch { case _: SecurityException => () } - } - m - } + def ensureAccessible(m: JMethod): JMethod = scala.reflect.ensureAccessible(m) def checkInitialized[T <: AnyRef](x: T): T = if (x == null) throw new UninitializedError else x @@ -224,7 +220,7 @@ object ScalaRunTime { if (iv == fv) return iv val lv = fv.toLong - if (lv == fv) return hash(lv) + if (lv == fv) hash(lv) else fv.hashCode } def hash(lv: Long): Int = { @@ -272,10 +268,20 @@ object ScalaRunTime { def isScalaClass(x: AnyRef) = packageOf(x) startsWith "scala." def isScalaCompilerClass(x: AnyRef) = packageOf(x) startsWith "scala.tools.nsc." + // We use reflection because the scala.xml package might not be available + def isSubClassOf(potentialSubClass: Class[_], ofClass: String) = + try { + val classLoader = potentialSubClass.getClassLoader + val clazz = Class.forName(ofClass, /*initialize =*/ false, classLoader) + clazz.isAssignableFrom(potentialSubClass) + } catch { + case cnfe: ClassNotFoundException => false + } + def isXmlNode(potentialSubClass: Class[_]) = isSubClassOf(potentialSubClass, "scala.xml.Node") + def isXmlMetaData(potentialSubClass: Class[_]) = isSubClassOf(potentialSubClass, "scala.xml.MetaData") + // When doing our own iteration is dangerous def useOwnToString(x: Any) = x match { - // Node extends NodeSeq extends Seq[Node] and MetaData extends Iterable[MetaData] - case _: Node | _: MetaData => true // Range/NumericRange have a custom toString to avoid walking a gazillion elements case _: Range | _: NumericRange[_] => true // Sorted collections to the wrong thing (for us) on iteration - ticket #3493 @@ -284,10 +290,12 @@ object ScalaRunTime { case _: StringLike[_] => true // Don't want to evaluate any elements in a view case _: TraversableView[_, _] => true + // Node extends NodeSeq extends Seq[Node] and MetaData extends Iterable[MetaData] + // -> catch those by isXmlNode and isXmlMetaData. // Don't want to a) traverse infinity or b) be overly helpful with peoples' custom // collections which may have useful toString methods - ticket #3710 // or c) print AbstractFiles which are somehow also Iterable[AbstractFile]s. - case x: Traversable[_] => !x.hasDefiniteSize || !isScalaClass(x) || isScalaCompilerClass(x) + case x: Traversable[_] => !x.hasDefiniteSize || !isScalaClass(x) || isScalaCompilerClass(x) || isXmlNode(x.getClass) || isXmlMetaData(x.getClass) // Otherwise, nothing could possibly go wrong case _ => false } @@ -328,7 +336,7 @@ object ScalaRunTime { // to be iterated, such as some scala.tools.nsc.io.AbstractFile derived classes. try inner(arg) catch { - case _: StackOverflowError | _: UnsupportedOperationException | _: AssertionError => "" + arg + case _: UnsupportedOperationException | _: AssertionError => "" + arg } } @@ -339,18 +347,17 @@ object ScalaRunTime { nl + s + "\n" } - private[scala] def checkZip(what: String, coll1: TraversableOnce[_], coll2: TraversableOnce[_]) { - if (sys.props contains "scala.debug.zip") { - val xs = coll1.toIndexedSeq - val ys = coll2.toIndexedSeq - if (xs.length != ys.length) { - Console.err.println( - "Mismatched zip in " + what + ":\n" + - " this: " + xs.mkString(", ") + "\n" + - " that: " + ys.mkString(", ") - ) - (new Exception).getStackTrace.drop(2).take(10).foreach(println) - } - } + + def box[T](clazz: jClass[T]): jClass[_] = clazz match { + case java.lang.Byte.TYPE => classOf[java.lang.Byte] + case java.lang.Short.TYPE => classOf[java.lang.Short] + case java.lang.Character.TYPE => classOf[java.lang.Character] + case java.lang.Integer.TYPE => classOf[java.lang.Integer] + case java.lang.Long.TYPE => classOf[java.lang.Long] + case java.lang.Float.TYPE => classOf[java.lang.Float] + case java.lang.Double.TYPE => classOf[java.lang.Double] + case java.lang.Void.TYPE => classOf[scala.runtime.BoxedUnit] + case java.lang.Boolean.TYPE => classOf[java.lang.Boolean] + case _ => clazz } } diff --git a/src/library/scala/runtime/SeqCharSequence.scala b/src/library/scala/runtime/SeqCharSequence.scala index d2084a6598..ce7d7afc9e 100644 --- a/src/library/scala/runtime/SeqCharSequence.scala +++ b/src/library/scala/runtime/SeqCharSequence.scala @@ -11,6 +11,7 @@ package runtime import java.util.Arrays.copyOfRange +@deprecated("Use Predef.SeqCharSequence", "2.11.0") final class SeqCharSequence(val xs: scala.collection.IndexedSeq[Char]) extends CharSequence { def length: Int = xs.length def charAt(index: Int): Char = xs(index) @@ -18,6 +19,8 @@ final class SeqCharSequence(val xs: scala.collection.IndexedSeq[Char]) extends C override def toString = xs.mkString("") } +// Still need this one since the implicit class ArrayCharSequence only converts +// a single argument. final class ArrayCharSequence(val xs: Array[Char], start: Int, end: Int) extends CharSequence { // yikes // java.lang.VerifyError: (class: scala/runtime/ArrayCharSequence, method: <init> signature: ([C)V) diff --git a/src/library/scala/runtime/ShortRef.java b/src/library/scala/runtime/ShortRef.java index 461b521e5f..e5e8de3d8b 100644 --- a/src/library/scala/runtime/ShortRef.java +++ b/src/library/scala/runtime/ShortRef.java @@ -17,4 +17,7 @@ public class ShortRef implements java.io.Serializable { public short elem; public ShortRef(short elem) { this.elem = elem; } public String toString() { return java.lang.Short.toString(elem); } + + public static ShortRef create(short e) { return new ShortRef(e); } + public static ShortRef zero() { return new ShortRef((short)0); } } diff --git a/src/library/scala/runtime/StringAdd.scala b/src/library/scala/runtime/StringAdd.scala index 9d848f0ba7..d5b51a6e92 100644 --- a/src/library/scala/runtime/StringAdd.scala +++ b/src/library/scala/runtime/StringAdd.scala @@ -6,9 +6,12 @@ ** ** \* */ -package scala.runtime +package scala +package runtime + /** A wrapper class that adds string concatenation `+` to any value */ +@deprecated("Use Predef.StringAdd", "2.11.0") final class StringAdd(val self: Any) extends AnyVal { def +(other: String) = String.valueOf(self) + other } diff --git a/src/library/scala/runtime/StringFormat.scala b/src/library/scala/runtime/StringFormat.scala index 983ae2fc54..de32ac7e86 100644 --- a/src/library/scala/runtime/StringFormat.scala +++ b/src/library/scala/runtime/StringFormat.scala @@ -6,10 +6,13 @@ ** ** \* */ -package scala.runtime +package scala +package runtime + /** A wrapper class that adds a `formatted` operation to any value */ +@deprecated("Use Predef.StringFormat", "2.11.0") final class StringFormat(val self: Any) extends AnyVal { /** Returns string formatted according to given `format` string. * Format strings are as for `String.format` diff --git a/src/library/scala/runtime/Tuple2Zipped.scala b/src/library/scala/runtime/Tuple2Zipped.scala index ef29075ac3..b28f6d4269 100644 --- a/src/library/scala/runtime/Tuple2Zipped.scala +++ b/src/library/scala/runtime/Tuple2Zipped.scala @@ -6,7 +6,9 @@ ** |/ ** \* */ -package scala.runtime +package scala +package runtime + import scala.collection.{ TraversableLike, IterableLike } import scala.collection.generic.{ CanBuildFrom => CBF } @@ -37,12 +39,12 @@ final class Tuple2Zipped[El1, Repr1, El2, Repr2](val colls: (TraversableLike[El1 for (el1 <- colls._1) { if (elems2.hasNext) - b += f(el1, elems2.next) + b += f(el1, elems2.next()) else - return b.result + return b.result() } - b.result + b.result() } def flatMap[B, To](f: (El1, El2) => TraversableOnce[B])(implicit cbf: CBF[Repr1, B, To]): To = { @@ -51,12 +53,12 @@ final class Tuple2Zipped[El1, Repr1, El2, Repr2](val colls: (TraversableLike[El1 for (el1 <- colls._1) { if (elems2.hasNext) - b ++= f(el1, elems2.next) + b ++= f(el1, elems2.next()) else - return b.result + return b.result() } - b.result + b.result() } def filter[To1, To2](f: (El1, El2) => Boolean)(implicit cbf1: CBF[Repr1, El1, To1], cbf2: CBF[Repr2, El2, To2]): (To1, To2) = { @@ -66,16 +68,16 @@ final class Tuple2Zipped[El1, Repr1, El2, Repr2](val colls: (TraversableLike[El1 for (el1 <- colls._1) { if (elems2.hasNext) { - val el2 = elems2.next + val el2 = elems2.next() if (f(el1, el2)) { b1 += el1 b2 += el2 } } - else return (b1.result, b2.result) + else return (b1.result(), b2.result()) } - (b1.result, b2.result) + (b1.result(), b2.result()) } def exists(f: (El1, El2) => Boolean): Boolean = { @@ -83,7 +85,7 @@ final class Tuple2Zipped[El1, Repr1, El2, Repr2](val colls: (TraversableLike[El1 for (el1 <- colls._1) { if (elems2.hasNext) { - if (f(el1, elems2.next)) + if (f(el1, elems2.next())) return true } else return false @@ -99,7 +101,7 @@ final class Tuple2Zipped[El1, Repr1, El2, Repr2](val colls: (TraversableLike[El1 for (el1 <- colls._1) { if (elems2.hasNext) - f(el1, elems2.next) + f(el1, elems2.next()) else return } @@ -117,9 +119,9 @@ object Tuple2Zipped { val it1 = x._1.toIterator val it2 = x._2.toIterator while (it1.hasNext && it2.hasNext) - buf += ((it1.next, it2.next)) + buf += ((it1.next(), it2.next())) - buf.result + buf.result() } def zipped[El1, Repr1, El2, Repr2] diff --git a/src/library/scala/runtime/Tuple3Zipped.scala b/src/library/scala/runtime/Tuple3Zipped.scala index 3f2afaf772..7c501380a3 100644 --- a/src/library/scala/runtime/Tuple3Zipped.scala +++ b/src/library/scala/runtime/Tuple3Zipped.scala @@ -6,7 +6,9 @@ ** |/ ** \* */ -package scala.runtime +package scala +package runtime + import scala.collection.{ TraversableLike, IterableLike } import scala.collection.generic.{ CanBuildFrom => CBF } @@ -34,11 +36,11 @@ final class Tuple3Zipped[El1, Repr1, El2, Repr2, El3, Repr3](val colls: (Travers for (el1 <- colls._1) { if (elems2.hasNext && elems3.hasNext) - b += f(el1, elems2.next, elems3.next) + b += f(el1, elems2.next(), elems3.next()) else - return b.result + return b.result() } - b.result + b.result() } def flatMap[B, To](f: (El1, El2, El3) => TraversableOnce[B])(implicit cbf: CBF[Repr1, B, To]): To = { @@ -48,11 +50,11 @@ final class Tuple3Zipped[El1, Repr1, El2, Repr2, El3, Repr3](val colls: (Travers for (el1 <- colls._1) { if (elems2.hasNext && elems3.hasNext) - b ++= f(el1, elems2.next, elems3.next) + b ++= f(el1, elems2.next(), elems3.next()) else - return b.result + return b.result() } - b.result + b.result() } def filter[To1, To2, To3](f: (El1, El2, El3) => Boolean)( @@ -64,12 +66,12 @@ final class Tuple3Zipped[El1, Repr1, El2, Repr2, El3, Repr3](val colls: (Travers val b3 = cbf3(colls._3.repr) val elems2 = colls._2.iterator val elems3 = colls._3.iterator - def result = (b1.result, b2.result, b3.result) + def result = (b1.result(), b2.result(), b3.result()) for (el1 <- colls._1) { if (elems2.hasNext && elems3.hasNext) { - val el2 = elems2.next - val el3 = elems3.next + val el2 = elems2.next() + val el3 = elems3.next() if (f(el1, el2, el3)) { b1 += el1 @@ -89,7 +91,7 @@ final class Tuple3Zipped[El1, Repr1, El2, Repr2, El3, Repr3](val colls: (Travers for (el1 <- colls._1) { if (elems2.hasNext && elems3.hasNext) { - if (f(el1, elems2.next, elems3.next)) + if (f(el1, elems2.next(), elems3.next())) return true } else return false @@ -106,7 +108,7 @@ final class Tuple3Zipped[El1, Repr1, El2, Repr2, El3, Repr3](val colls: (Travers for (el1 <- colls._1) { if (elems2.hasNext && elems3.hasNext) - f(el1, elems2.next, elems3.next) + f(el1, elems2.next(), elems3.next()) else return } @@ -126,9 +128,9 @@ object Tuple3Zipped { val it2 = x._2.toIterator val it3 = x._3.toIterator while (it1.hasNext && it2.hasNext && it3.hasNext) - buf += ((it1.next, it2.next, it3.next)) + buf += ((it1.next(), it2.next(), it3.next())) - buf.result + buf.result() } def zipped[El1, Repr1, El2, Repr2, El3, Repr3] diff --git a/src/library/scala/runtime/VolatileBooleanRef.java b/src/library/scala/runtime/VolatileBooleanRef.java index e3bd182345..ef5b691118 100755 --- a/src/library/scala/runtime/VolatileBooleanRef.java +++ b/src/library/scala/runtime/VolatileBooleanRef.java @@ -17,4 +17,7 @@ public class VolatileBooleanRef implements java.io.Serializable { volatile public boolean elem; public VolatileBooleanRef(boolean elem) { this.elem = elem; } public String toString() { return String.valueOf(elem); } + + public static VolatileBooleanRef create(boolean e) { return new VolatileBooleanRef(e); } + public static VolatileBooleanRef zero() { return new VolatileBooleanRef(false); } } diff --git a/src/library/scala/runtime/VolatileByteRef.java b/src/library/scala/runtime/VolatileByteRef.java index 034b003017..d792b0a386 100755 --- a/src/library/scala/runtime/VolatileByteRef.java +++ b/src/library/scala/runtime/VolatileByteRef.java @@ -17,4 +17,7 @@ public class VolatileByteRef implements java.io.Serializable { volatile public byte elem; public VolatileByteRef(byte elem) { this.elem = elem; } public String toString() { return java.lang.Byte.toString(elem); } + + public static VolatileByteRef create(byte e) { return new VolatileByteRef(e); } + public static VolatileByteRef zero() { return new VolatileByteRef((byte)0); } } diff --git a/src/library/scala/runtime/VolatileCharRef.java b/src/library/scala/runtime/VolatileCharRef.java index f90648c5e9..555b171283 100755 --- a/src/library/scala/runtime/VolatileCharRef.java +++ b/src/library/scala/runtime/VolatileCharRef.java @@ -17,4 +17,7 @@ public class VolatileCharRef implements java.io.Serializable { volatile public char elem; public VolatileCharRef(char elem) { this.elem = elem; } public String toString() { return java.lang.Character.toString(elem); } + + public static VolatileCharRef create(char e) { return new VolatileCharRef(e); } + public static VolatileCharRef zero() { return new VolatileCharRef((char)0); } } diff --git a/src/library/scala/runtime/VolatileDoubleRef.java b/src/library/scala/runtime/VolatileDoubleRef.java index d47c9578c6..1932055c6a 100755 --- a/src/library/scala/runtime/VolatileDoubleRef.java +++ b/src/library/scala/runtime/VolatileDoubleRef.java @@ -16,4 +16,7 @@ public class VolatileDoubleRef implements java.io.Serializable { volatile public double elem; public VolatileDoubleRef(double elem) { this.elem = elem; } public String toString() { return java.lang.Double.toString(elem); } + + public static VolatileDoubleRef create(double e) { return new VolatileDoubleRef(e); } + public static VolatileDoubleRef zero() { return new VolatileDoubleRef(0); } } diff --git a/src/library/scala/runtime/VolatileFloatRef.java b/src/library/scala/runtime/VolatileFloatRef.java index 97da95f7cc..3a81be1146 100755 --- a/src/library/scala/runtime/VolatileFloatRef.java +++ b/src/library/scala/runtime/VolatileFloatRef.java @@ -17,4 +17,7 @@ public class VolatileFloatRef implements java.io.Serializable { volatile public float elem; public VolatileFloatRef(float elem) { this.elem = elem; } public String toString() { return java.lang.Float.toString(elem); } + + public static VolatileFloatRef create(float e) { return new VolatileFloatRef(e); } + public static VolatileFloatRef zero() { return new VolatileFloatRef(0); } } diff --git a/src/library/scala/runtime/VolatileIntRef.java b/src/library/scala/runtime/VolatileIntRef.java index e8a68a1a9a..ae015bc8b1 100755 --- a/src/library/scala/runtime/VolatileIntRef.java +++ b/src/library/scala/runtime/VolatileIntRef.java @@ -16,4 +16,7 @@ public class VolatileIntRef implements java.io.Serializable { volatile public int elem; public VolatileIntRef(int elem) { this.elem = elem; } public String toString() { return java.lang.Integer.toString(elem); } + + public static VolatileIntRef create(int e) { return new VolatileIntRef(e); } + public static VolatileIntRef zero() { return new VolatileIntRef(0); } } diff --git a/src/library/scala/runtime/VolatileLongRef.java b/src/library/scala/runtime/VolatileLongRef.java index 80e627cd4b..e596f5aa69 100755 --- a/src/library/scala/runtime/VolatileLongRef.java +++ b/src/library/scala/runtime/VolatileLongRef.java @@ -17,4 +17,7 @@ public class VolatileLongRef implements java.io.Serializable { volatile public long elem; public VolatileLongRef(long elem) { this.elem = elem; } public String toString() { return java.lang.Long.toString(elem); } + + public static VolatileLongRef create(long e) { return new VolatileLongRef(e); } + public static VolatileLongRef zero() { return new VolatileLongRef(0); } } diff --git a/src/library/scala/runtime/VolatileObjectRef.java b/src/library/scala/runtime/VolatileObjectRef.java index 848b0632ea..6063501ffb 100755 --- a/src/library/scala/runtime/VolatileObjectRef.java +++ b/src/library/scala/runtime/VolatileObjectRef.java @@ -16,5 +16,9 @@ public class VolatileObjectRef<T> implements java.io.Serializable { volatile public T elem; public VolatileObjectRef(T elem) { this.elem = elem; } + @Override public String toString() { return String.valueOf(elem); } + + public static <U> VolatileObjectRef<U> create(U e) { return new VolatileObjectRef<U>(e); } + public static VolatileObjectRef<Object> zero() { return new VolatileObjectRef<Object>(null); } } diff --git a/src/library/scala/runtime/VolatileShortRef.java b/src/library/scala/runtime/VolatileShortRef.java index 4e91d0dc70..0a2825941f 100755 --- a/src/library/scala/runtime/VolatileShortRef.java +++ b/src/library/scala/runtime/VolatileShortRef.java @@ -17,4 +17,7 @@ public class VolatileShortRef implements java.io.Serializable { volatile public short elem; public VolatileShortRef(short elem) { this.elem = elem; } public String toString() { return java.lang.Short.toString(elem); } + + public static VolatileShortRef create(short e) { return new VolatileShortRef(e); } + public static VolatileShortRef zero() { return new VolatileShortRef((short)0); } } diff --git a/src/library/scala/runtime/WorksheetSupport.scala b/src/library/scala/runtime/WorksheetSupport.scala deleted file mode 100644 index 016a0d04e0..0000000000 --- a/src/library/scala/runtime/WorksheetSupport.scala +++ /dev/null @@ -1,94 +0,0 @@ -package scala.runtime -import java.io.{OutputStream, PrintStream} -import scala.runtime.ScalaRunTime.stringOf - -/** A utility object that's needed by the code that executes a worksheet. - */ -@deprecated("SI-6458: Instrumentation logic will be moved out of the compiler.","2.10.0") -object WorksheetSupport { - - /** The offset in the source which should be printed */ - private var currentOffset = 0 - - /** A stream that flushes in regular intervals so that output can be captured - * in real time. The flush interval is determined by the field "flushInterval". - * By default it is 30ms. - */ - private class FlushedOutputStream(out: OutputStream) extends OutputStream { - protected def flushInterval = 30000000L // interval between flushes, by default 30ms - protected def width = 80 // output width, by default 80 characters - protected def tabInc = 8 // tab increment, by default 8 characters - private var lastFlush: Long = 0L - private var col = -1 - override def write(b: Array[Byte], off: Int, len: Int) = { - for (idx <- off until (off + len min b.length)) writeOne(b(idx)) - flush() - } - override def write(c: Int) { - writeOne(c) - flush() - } - override def flush() { - val current = System.nanoTime - if (current - lastFlush >= flushInterval) { - out.flush() - lastFlush = current - } - } - def writeOne(c: Int) { - if (col < 0) { - col = 0 - write((currentOffset+" ").getBytes) - } - out.write(c) - col = - if (c == '\n') -1 - else if (c == '\t') (col / tabInc) * tabInc + tabInc - else col + 1 - if (col >= width) writeOne('\n') - } - def ensureNewLine() = if (col > 0) writeOne('\n') - } - - private val flushedOut = new FlushedOutputStream(System.out) - private val printOut = new PrintStream(flushedOut) - - private def redirected(op: => Unit) = { - val oldSysOut = System.out - val oldSysErr = System.err - val oldConsOut = Console.out - val oldConsErr = Console.err - System.setOut(printOut) - System.setErr(printOut) - Console.setOut(printOut) - Console.setErr(printOut) - try op - finally { - printOut.close() - System.setOut(oldSysOut) - System.setErr(oldSysErr) - Console.setOut(oldConsOut) - Console.setErr(oldConsErr) - } - } - - def $execute(op: => Unit) = redirected { - try op - catch { - case ex: StopException => ; - case ex: Throwable => ex.printStackTrace() - } - } - - def $skip(n: Int) = { - flushedOut.ensureNewLine() - currentOffset += n - } - - def $stop() = throw new StopException - - def $show(x: Any): String = stringOf(x) -} - -class StopException extends Exception - diff --git a/src/library/scala/sys/BooleanProp.scala b/src/library/scala/sys/BooleanProp.scala index e3c25bbd11..74b0a9077b 100644 --- a/src/library/scala/sys/BooleanProp.scala +++ b/src/library/scala/sys/BooleanProp.scala @@ -6,7 +6,8 @@ ** |/ ** \* */ -package scala.sys +package scala +package sys import scala.language.implicitConversions diff --git a/src/library/scala/sys/PropImpl.scala b/src/library/scala/sys/PropImpl.scala index b50e0e18a7..3b451ab1d9 100644 --- a/src/library/scala/sys/PropImpl.scala +++ b/src/library/scala/sys/PropImpl.scala @@ -6,7 +6,8 @@ ** |/ ** \* */ -package scala.sys +package scala +package sys import scala.collection.mutable diff --git a/src/library/scala/sys/ShutdownHookThread.scala b/src/library/scala/sys/ShutdownHookThread.scala index a8f4871870..6018ac852b 100644 --- a/src/library/scala/sys/ShutdownHookThread.scala +++ b/src/library/scala/sys/ShutdownHookThread.scala @@ -6,7 +6,8 @@ ** |/ ** \* */ -package scala.sys +package scala +package sys /** A minimal Thread wrapper to enhance shutdown hooks. It knows * how to unregister itself. diff --git a/src/library/scala/sys/SystemProperties.scala b/src/library/scala/sys/SystemProperties.scala index da9adb3dc2..39f66f5030 100644 --- a/src/library/scala/sys/SystemProperties.scala +++ b/src/library/scala/sys/SystemProperties.scala @@ -6,7 +6,8 @@ ** |/ ** \* */ -package scala.sys +package scala +package sys import scala.collection.{ mutable, Iterator } import scala.collection.JavaConverters._ @@ -64,7 +65,6 @@ object SystemProperties { propertyHelp(p.key) = helpText p } - private def str(key: String, helpText: String) = addHelp(Prop[String](key), helpText) private def bool(key: String, helpText: String): BooleanProp = addHelp[BooleanProp]( if (key startsWith "java.") BooleanProp.valueIsTrue(key) else BooleanProp.keyExists(key), helpText diff --git a/src/library/scala/sys/process/BasicIO.scala b/src/library/scala/sys/process/BasicIO.scala index 0003df6c52..b31bbf0540 100644 --- a/src/library/scala/sys/process/BasicIO.scala +++ b/src/library/scala/sys/process/BasicIO.scala @@ -6,7 +6,8 @@ ** |/ ** \* */ -package scala.sys +package scala +package sys package process import processInternal._ @@ -46,7 +47,7 @@ object BasicIO { def next(): Stream[T] = q.take match { case Left(0) => Stream.empty case Left(code) => if (nonzeroException) scala.sys.error("Nonzero exit code: " + code) else Stream.empty - case Right(s) => Stream.cons(s, next) + case Right(s) => Stream.cons(s, next()) } new Streamed((s: T) => q put Right(s), code => q put Left(code), () => next()) } @@ -161,21 +162,29 @@ object BasicIO { */ def processFully(processLine: String => Unit): InputStream => Unit = in => { val reader = new BufferedReader(new InputStreamReader(in)) - processLinesFully(processLine)(reader.readLine) - reader.close() + try processLinesFully(processLine)(reader.readLine) + finally reader.close() } /** Calls `processLine` with the result of `readLine` until the latter returns - * `null`. - */ + * `null` or the current thread is interrupted. + */ def processLinesFully(processLine: String => Unit)(readLine: () => String) { - def readFully() { - val line = readLine() - if (line != null) { - processLine(line) - readFully() + def working = (Thread.currentThread.isInterrupted == false) + def halting = { Thread.currentThread.interrupt(); null } + def readFully(): Unit = + if (working) { + val line = + try readLine() + catch { + case _: InterruptedException => halting + case e: IOException if !working => halting + } + if (line != null) { + processLine(line) + readFully() + } } - } readFully() } diff --git a/src/library/scala/sys/process/Process.scala b/src/library/scala/sys/process/Process.scala index 715b364e08..dcd06c89e9 100644 --- a/src/library/scala/sys/process/Process.scala +++ b/src/library/scala/sys/process/Process.scala @@ -6,7 +6,8 @@ ** |/ ** \* */ -package scala.sys +package scala +package sys package process import processInternal._ @@ -126,15 +127,6 @@ trait ProcessCreation { */ def apply(url: URL): URLBuilder = new URLImpl(url) - /** Creates a [[scala.sys.process.ProcessBuilder]] from a Scala XML Element. - * This can be used as a way to template strings. - * - * @example {{{ - * apply(<x> {dxPath.absolutePath} --dex --output={classesDexPath.absolutePath} {classesMinJarPath.absolutePath}</x>) - * }}} - */ - def apply(command: scala.xml.Elem): ProcessBuilder = apply(command.text.trim) - /** Creates a [[scala.sys.process.ProcessBuilder]] from a `Boolean`. This can be * to force an exit value. */ @@ -219,14 +211,6 @@ trait ProcessImplicits { */ implicit def urlToProcess(url: URL): URLBuilder = apply(url) - /** Implicitly convert a [[scala.xml.Elem]] into a - * [[scala.sys.process.ProcessBuilder]]. This is done by obtaining the text - * elements of the element, trimming spaces, and then converting the result - * from string to a process. Importantly, tags are completely ignored, so - * they cannot be used to separate parameters. - */ - implicit def xmlToProcess(command: scala.xml.Elem): ProcessBuilder = apply(command) - /** Implicitly convert a `String` into a [[scala.sys.process.ProcessBuilder]]. */ implicit def stringToProcess(command: String): ProcessBuilder = apply(command) diff --git a/src/library/scala/sys/process/ProcessBuilder.scala b/src/library/scala/sys/process/ProcessBuilder.scala index d0b2ecfe73..ac86495001 100644 --- a/src/library/scala/sys/process/ProcessBuilder.scala +++ b/src/library/scala/sys/process/ProcessBuilder.scala @@ -6,7 +6,8 @@ ** |/ ** \* */ -package scala.sys +package scala +package sys package process import processInternal._ @@ -23,15 +24,13 @@ import ProcessBuilder._ * based on these factories made available in the package object * [[scala.sys.process]]. Here are some examples: * {{{ - * import.scala.sys.process._ + * import scala.sys.process._ * * // Executes "ls" and sends output to stdout * "ls".! * * // Execute "ls" and assign a `Stream[String]` of its output to "contents". - * // Because [[scala.Predef]] already defines a `lines` method for `String`, - * // we use [[scala.sys.process.Process]]'s object companion to create it. - * val contents = Process("ls").lines + * val contents = Process("ls").lineStream * * // Here we use a `Seq` to make the parameter whitespace-safe * def contentsOf(dir: String): String = Seq("ls", dir).!! @@ -46,14 +45,14 @@ import ProcessBuilder._ * * Two existing `ProcessBuilder` can be combined in the following ways: * - * * They can be executed in parallel, with the output of the first being fed - * as input to the second, like Unix pipes. This is achieved with the `#|` - * method. - * * They can be executed in sequence, with the second starting as soon as - * the first ends. This is done by the `###` method. - * * The execution of the second one can be conditioned by the return code - * (exit status) of the first, either only when it's zero, or only when it's - * not zero. The methods `#&&` and `#||` accomplish these tasks. + * - They can be executed in parallel, with the output of the first being fed + * as input to the second, like Unix pipes. This is achieved with the `#|` + * method. + * - They can be executed in sequence, with the second starting as soon as + * the first ends. This is done by the `###` method. + * - The execution of the second one can be conditioned by the return code + * (exit status) of the first, either only when it's zero, or only when it's + * not zero. The methods `#&&` and `#||` accomplish these tasks. * * ==Redirecting Input/Output== * @@ -61,7 +60,7 @@ import ProcessBuilder._ * there's a few methods that create a new `ProcessBuilder` with a * pre-configured input or output. They are `#<`, `#>` and `#>>`, and may take * as input either another `ProcessBuilder` (like the pipe described above), or - * something else such as a `java.io.File` or a `java.lang.InputStream`. + * something else such as a `java.io.File` or a `java.io.InputStream`. * For example: * {{{ * new URL("http://databinder.net/dispatch/About") #> "grep JSON" #>> new File("About_JSON") ! @@ -74,18 +73,18 @@ import ProcessBuilder._ * overloads and variations to enable further control over the I/O. These * methods are: * - * * `run`: the most general method, it returns a - * [[scala.sys.process.Process]] immediately, and the external command - * executes concurrently. - * * `!`: blocks until all external commands exit, and returns the exit code - * of the last one in the chain of execution. - * * `!!`: blocks until all external commands exit, and returns a `String` - * with the output generated. - * * `lines`: returns immediately like `run`, and the output being generared - * is provided through a `Stream[String]`. Getting the next element of that - * `Stream` may block until it becomes available. This method will throw an - * exception if the return code is different than zero -- if this is not - * desired, use the `lines_!` method. + * - `run`: the most general method, it returns a + * [[scala.sys.process.Process]] immediately, and the external command + * executes concurrently. + * - `!`: blocks until all external commands exit, and returns the exit code + * of the last one in the chain of execution. + * - `!!`: blocks until all external commands exit, and returns a `String` + * with the output generated. + * - `lineStream`: returns immediately like `run`, and the output being generated + * is provided through a `Stream[String]`. Getting the next element of that + * `Stream` may block until it becomes available. This method will throw an + * exception if the return code is different than zero -- if this is not + * desired, use the `lineStream_!` method. * * ==Handling Input and Output== * @@ -122,14 +121,22 @@ import ProcessBuilder._ * 1. `#&&` conditionally executes the second command if the previous one finished with * exit value 0. It mirrors shell's `&&`. * 1. `#||` conditionally executes the third command if the exit value of the previous - * command is different than zero. It mirrors shell's `&&`. + * command is different than zero. It mirrors shell's `||`. * * Finally, `!` at the end executes the commands, and returns the exit value. * Whatever is printed will be sent to the Scala process standard output. If - * we wanted to caputre it, we could run that with `!!` instead. + * we wanted to capture it, we could run that with `!!` instead. * * Note: though it is not shown above, the equivalent of a shell's `;` would be * `###`. The reason for this name is that `;` is a reserved token in Scala. + * + * Note: the `lines` method, though deprecated, may conflict with the `StringLike` + * method of the same name. To avoid this, one may wish to call the builders in + * `Process` instead of importing `scala.sys.process._`. The example above would be + * {{{ + * import scala.sys.process.Process + * Process("find src -name *.scala -exec grep null {} ;") #| Process("xargs test -z") #&& Process("echo null-free") #|| Process("echo null detected") ! + * }}} */ trait ProcessBuilder extends Source with Sink { /** Starts the process represented by this builder, blocks until it exits, and @@ -164,15 +171,23 @@ trait ProcessBuilder extends Source with Sink { * with a non-zero value, the Stream will provide all lines up to termination * and then throw an exception. */ - def lines: Stream[String] + def lineStream: Stream[String] + + /** Deprecated (renamed). Use `lineStream` instead. */ + @deprecated("Use lineStream instead.", "2.11.0") + def lines: Stream[String] = lineStream /** Starts the process represented by this builder. The output is returned as * a Stream that blocks when lines are not available but the process has not * completed. Standard error is sent to the provided ProcessLogger. If the * process exits with a non-zero value, the Stream will provide all lines up - * to termination but will not throw an exception. + * to termination and then throw an exception. */ - def lines(log: ProcessLogger): Stream[String] + def lineStream(log: ProcessLogger): Stream[String] + + /** Deprecated (renamed). Use `lineStream(log: ProcessLogger)` instead. */ + @deprecated("Use stream instead.", "2.11.0") + def lines(log: ProcessLogger): Stream[String] = lineStream(log) /** Starts the process represented by this builder. The output is returned as * a Stream that blocks when lines are not available but the process has not @@ -180,7 +195,11 @@ trait ProcessBuilder extends Source with Sink { * with a non-zero value, the Stream will provide all lines up to termination * but will not throw an exception. */ - def lines_! : Stream[String] + def lineStream_! : Stream[String] + + /** Deprecated (renamed). Use `lineStream_!` instead. */ + @deprecated("Use lineStream_! instead.", "2.11.0") + def lines_! : Stream[String] = lineStream_! /** Starts the process represented by this builder. The output is returned as * a Stream that blocks when lines are not available but the process has not @@ -188,7 +207,11 @@ trait ProcessBuilder extends Source with Sink { * process exits with a non-zero value, the Stream will provide all lines up * to termination but will not throw an exception. */ - def lines_!(log: ProcessLogger): Stream[String] + def lineStream_!(log: ProcessLogger): Stream[String] + + /** Deprecated (renamed). Use `lineStream_!(log: ProcessLogger)` instead. */ + @deprecated("Use stream_! instead.", "2.11.0") + def lines_!(log: ProcessLogger): Stream[String] = lineStream_!(log) /** Starts the process represented by this builder, blocks until it exits, and * returns the exit code. Standard output and error are sent to the console. @@ -305,10 +328,10 @@ object ProcessBuilder extends ProcessBuilderImpl { protected def toSource: ProcessBuilder /** Writes the output stream of this process to the given file. */ - def #> (f: File): ProcessBuilder = toFile(f, false) + def #> (f: File): ProcessBuilder = toFile(f, append = false) /** Appends the output stream of this process to the given file. */ - def #>> (f: File): ProcessBuilder = toFile(f, true) + def #>> (f: File): ProcessBuilder = toFile(f, append = true) /** Writes the output stream of this process to the given OutputStream. The * argument is call-by-name, so the stream is recreated, written, and closed each diff --git a/src/library/scala/sys/process/ProcessBuilderImpl.scala b/src/library/scala/sys/process/ProcessBuilderImpl.scala index 49fea6f464..236baaf038 100644 --- a/src/library/scala/sys/process/ProcessBuilderImpl.scala +++ b/src/library/scala/sys/process/ProcessBuilderImpl.scala @@ -6,7 +6,8 @@ ** |/ ** \* */ -package scala.sys +package scala +package sys package process import processInternal._ @@ -69,7 +70,7 @@ private[process] trait ProcessBuilderImpl { import io._ // spawn threads that process the input, output, and error streams using the functions defined in `io` - val inThread = Spawn(writeInput(process.getOutputStream), true) + val inThread = Spawn(writeInput(process.getOutputStream), daemon = true) val outThread = Spawn(processOutput(process.getInputStream), daemonizeThreads) val errorThread = if (p.redirectErrorStream) Nil @@ -93,26 +94,26 @@ private[process] trait ProcessBuilderImpl { def #&&(other: ProcessBuilder): ProcessBuilder = new AndBuilder(this, other) def ###(other: ProcessBuilder): ProcessBuilder = new SequenceBuilder(this, other) - def run(): Process = run(false) + def run(): Process = run(connectInput = false) def run(connectInput: Boolean): Process = run(BasicIO.standard(connectInput)) - def run(log: ProcessLogger): Process = run(log, false) + def run(log: ProcessLogger): Process = run(log, connectInput = false) def run(log: ProcessLogger, connectInput: Boolean): Process = run(BasicIO(connectInput, log)) - def !! = slurp(None, false) - def !!(log: ProcessLogger) = slurp(Some(log), false) - def !!< = slurp(None, true) - def !!<(log: ProcessLogger) = slurp(Some(log), true) + def !! = slurp(None, withIn = false) + def !!(log: ProcessLogger) = slurp(Some(log), withIn = false) + def !!< = slurp(None, withIn = true) + def !!<(log: ProcessLogger) = slurp(Some(log), withIn = true) - def lines: Stream[String] = lines(false, true, None) - def lines(log: ProcessLogger): Stream[String] = lines(false, true, Some(log)) - def lines_! : Stream[String] = lines(false, false, None) - def lines_!(log: ProcessLogger): Stream[String] = lines(false, false, Some(log)) + def lineStream: Stream[String] = lineStream(withInput = false, nonZeroException = true, None) + def lineStream(log: ProcessLogger): Stream[String] = lineStream(withInput = false, nonZeroException = true, Some(log)) + def lineStream_! : Stream[String] = lineStream(withInput = false, nonZeroException = false, None) + def lineStream_!(log: ProcessLogger): Stream[String] = lineStream(withInput = false, nonZeroException = false, Some(log)) - def ! = run(false).exitValue() + def ! = run(connectInput = false).exitValue() def !(io: ProcessIO) = run(io).exitValue() - def !(log: ProcessLogger) = runBuffered(log, false) - def !< = run(true).exitValue() - def !<(log: ProcessLogger) = runBuffered(log, true) + def !(log: ProcessLogger) = runBuffered(log, connectInput = false) + def !< = run(connectInput = true).exitValue() + def !<(log: ProcessLogger) = runBuffered(log, connectInput = true) /** Constructs a new builder which runs this command with all input/output threads marked * as daemon threads. This allows the creation of a long running process while still @@ -131,7 +132,7 @@ private[process] trait ProcessBuilderImpl { else scala.sys.error("Nonzero exit value: " + code) } - private[this] def lines( + private[this] def lineStream( withInput: Boolean, nonZeroException: Boolean, log: Option[ProcessLogger] diff --git a/src/library/scala/sys/process/ProcessIO.scala b/src/library/scala/sys/process/ProcessIO.scala index f5b26680d9..eedf667c88 100644 --- a/src/library/scala/sys/process/ProcessIO.scala +++ b/src/library/scala/sys/process/ProcessIO.scala @@ -6,7 +6,8 @@ ** |/ ** \* */ -package scala.sys +package scala +package sys package process import processInternal._ diff --git a/src/library/scala/sys/process/ProcessImpl.scala b/src/library/scala/sys/process/ProcessImpl.scala index c21c0daa5e..2b7fcdeb73 100644 --- a/src/library/scala/sys/process/ProcessImpl.scala +++ b/src/library/scala/sys/process/ProcessImpl.scala @@ -6,7 +6,8 @@ ** |/ ** \* */ -package scala.sys +package scala +package sys package process import processInternal._ @@ -17,7 +18,7 @@ private[process] trait ProcessImpl { /** Runs provided code in a new Thread and returns the Thread instance. */ private[process] object Spawn { - def apply(f: => Unit): Thread = apply(f, false) + def apply(f: => Unit): Thread = apply(f, daemon = false) def apply(f: => Unit, daemon: Boolean): Thread = { val thread = new Thread() { override def run() = { f } } thread.setDaemon(daemon) @@ -32,7 +33,7 @@ private[process] trait ProcessImpl { try result set Right(f) catch { case e: Exception => result set Left(e) } - Spawn(run) + Spawn(run()) () => result.get match { case Right(value) => value @@ -68,10 +69,10 @@ private[process] trait ProcessImpl { protected[this] override def runAndExitValue() = { val first = a.run(io) - runInterruptible(first.exitValue)(first.destroy()) flatMap { codeA => + runInterruptible(first.exitValue())(first.destroy()) flatMap { codeA => if (evaluateSecondProcess(codeA)) { val second = b.run(io) - runInterruptible(second.exitValue)(second.destroy()) + runInterruptible(second.exitValue())(second.destroy()) } else Some(codeA) } @@ -132,10 +133,10 @@ private[process] trait ProcessImpl { val first = a.run(firstIO) try { runInterruptible { - val exit1 = first.exitValue + val exit1 = first.exitValue() currentSource put None currentSink put None - val exit2 = second.exitValue + val exit2 = second.exitValue() // Since file redirection (e.g. #>) is implemented as a piped process, // we ignore its exit value so cmd #> file doesn't always return 0. if (b.hasExitValue) exit2 else exit1 @@ -222,8 +223,8 @@ private[process] trait ProcessImpl { p.exitValue() } override def destroy() = { - try{ - outputThreads foreach (_.stop()) + try { + outputThreads foreach (_.interrupt()) // on destroy, don't bother consuming any more output p.destroy() } finally inputThread.interrupt() diff --git a/src/library/scala/sys/process/ProcessLogger.scala b/src/library/scala/sys/process/ProcessLogger.scala index a4acb065d0..ae347221ef 100644 --- a/src/library/scala/sys/process/ProcessLogger.scala +++ b/src/library/scala/sys/process/ProcessLogger.scala @@ -6,7 +6,8 @@ ** |/ ** \* */ -package scala.sys +package scala +package sys package process import java.io._ diff --git a/src/library/scala/sys/process/package.scala b/src/library/scala/sys/process/package.scala index ed436febc0..1340a6c415 100644 --- a/src/library/scala/sys/process/package.scala +++ b/src/library/scala/sys/process/package.scala @@ -25,7 +25,7 @@ package scala.sys { * * {{{ * import scala.sys.process._ - * "ls" #| "grep .scala" #&& "scalac *.scala" #|| "echo nothing found" lines + * "ls" #| "grep .scala" #&& Seq("sh", "-c", "scalac *.scala") #|| "echo nothing found" lines * }}} * * We describe below the general concepts and architecture of the package, @@ -80,10 +80,7 @@ package scala.sys { * spaces -- no escaping of spaces is possible -- or out of a * [[scala.collection.Seq]], where the first element represents the command * name, and the remaining elements are arguments to it. In this latter case, - * arguments may contain spaces. One can also implicitly convert - * [[scala.xml.Elem]] and `java.lang.ProcessBuilder` into a `ProcessBuilder`. - * In the introductory example, the strings were converted into - * `ProcessBuilder` implicitly. + * arguments may contain spaces. * * To further control what how the process will be run, such as specifying * the directory in which it will be run, see the factories on @@ -154,7 +151,7 @@ package scala.sys { * * // An overly complex way of computing size of a compressed file * def gzFileSize(name: String) = { - * val cat = Seq("zcat", "name") + * val cat = Seq("zcat", name) * var count = 0 * def byteCounter(input: java.io.InputStream) = { * while(input.read() != -1) count += 1 diff --git a/src/library/scala/testing/Benchmark.scala b/src/library/scala/testing/Benchmark.scala deleted file mode 100644 index 66d7d448eb..0000000000 --- a/src/library/scala/testing/Benchmark.scala +++ /dev/null @@ -1,114 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala.testing - -import scala.compat.Platform - -/** `Benchmark` can be used to quickly turn an existing class into a - * benchmark. Here is a short example: - * {{{ - * object sort1 extends Sorter with Benchmark { - * def run = sort(List.range(1, 1000)) - * } - * }}} - * The `run` method has to be defined by the user, who will perform the - * timed operation there. Run the benchmark as follows: - * {{{ - * > scala sort1 5 - * }}} - * This will run the benchmark 5 times, forcing a garbage collection - * between runs, and printing the execution times to stdout. - * - * It is also possible to add a multiplier, so - * {{{ - * > scala sort1 5 10 - * }}} - * will run the entire benchmark 10 times, each time for 5 runs. - * - * @author Iulian Dragos, Burak Emir - */ -@deprecated("This class will be removed.", "2.10.0") -trait Benchmark { - - /** this method should be implemented by the concrete benchmark. - * This method is called by the benchmarking code for a number of times. - * The GC is called between "multiplier" calls to run, right after tear - * down. - * - * @see setUp - * @see tearDown - */ - def run() - - var multiplier = 1 - - /** Run the benchmark the specified number of times and return a list with - * the execution times in milliseconds in reverse order of the execution. - */ - def runBenchmark(noTimes: Int): List[Long] = - for (i <- List.range(1, noTimes + 1)) yield { - setUp - val startTime = Platform.currentTime - var i = 0; while (i < multiplier) { - run() - i += 1 - } - val stopTime = Platform.currentTime - tearDown - Platform.collectGarbage - - stopTime - startTime - } - - /** Prepare any data needed by the benchmark, but whose execution time - * should not be measured. This method is run before each call to the - * benchmark payload, 'run'. - */ - def setUp() {} - - /** Perform cleanup operations after each 'run'. For micro benchmarks, - * think about using the result of 'run' in a way that prevents the JVM - * to dead-code eliminate the whole 'run' method. For instance, print or - * write the results to a file. The execution time of this method is not - * measured. - */ - def tearDown() {} - - /** a string that is written at the beginning of the output line - * that contains the timings. By default, this is the class name. - */ - def prefix: String = getClass().getName() - - /** - * The entry point. It takes two arguments: - * - argument `n` is the number of consecutive runs - * - optional argument `mult` specifies that the `n` runs are repeated - * `mult` times. - */ - def main(args: Array[String]) { - if (args.length > 0) { - val logFile = new java.io.OutputStreamWriter(System.out) - if (args.length > 1) multiplier = args(1).toInt - logFile.write(prefix) - for (t <- runBenchmark(args(0).toInt)) - logFile.write("\t" + t) - - logFile.write(Platform.EOL) - logFile.flush() - } else { - println("Usage: scala benchmarks.program <runs> ") - println(" or: scala benchmarks.program <runs> <multiplier>") - println(""" - The benchmark is run <runs> times, forcing a garbage collection between runs. The optional - <multiplier> causes the benchmark to be repeated <multiplier> times, each time for <runs> - executions. - """) - } - } -} diff --git a/src/library/scala/testing/Show.scala b/src/library/scala/testing/Show.scala deleted file mode 100644 index 9376e26db4..0000000000 --- a/src/library/scala/testing/Show.scala +++ /dev/null @@ -1,75 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - - -package scala.testing - -/** Classes inheriting trait `Show` can test their member methods using the - * notation `meth(arg,,1,,, ..., arg,,n,,)`, where `meth` is the name of - * the method and `arg,,1,,,...,arg,,n,,` are the arguments. - * - * The only difference to a normal method call is the leading quote - * character (`'`). A quoted method call like the one above will produces - * a legible diagnostic to be printed on [[scala.Console]]. - * - * It is of the form - * - * `meth(arg,,1,,, ..., arg,,n,,)` gives `<result>` - * - * where `<result>` is the result of evaluating the call. - * - */ -@deprecated("This class will be removed.", "2.10.0") -trait Show { - - /** An implicit definition that adds an apply method to Symbol which forwards to `test`. - * Prints out diagnostics of method applications. - */ - implicit class SymApply(f: Symbol) { - def apply[A](args: A*) { - println(test(f, args: _*)) - } - } - - @deprecated("use SymApply instead", "2.10.0") - def symApply(sym: Symbol): SymApply = new SymApply(sym) - - /** Apply method with name of given symbol `f` to given arguments and return - * a result diagnostics. - */ - def test[A](f: Symbol, args: A*): String = { - val args1 = args map (_.asInstanceOf[AnyRef]) - def testMethod(meth: java.lang.reflect.Method): String = - f.name+"("+(args mkString ",")+") gives "+ - { - try { - meth.invoke(this, args1: _*) - } catch { - case ex: IllegalAccessException => ex - case ex: IllegalArgumentException => ex - case ex: java.lang.reflect.InvocationTargetException => ex - } - } - getClass.getMethods.toList filter (_.getName == f.name) match { - case List() => - f.name+" is not defined" - case List(m) => - testMethod(m) - case ms => // multiple methods, disambiguate by number of arguments - ms filter (_.getParameterTypes.length == args.length) match { - case List() => - testMethod(ms.head) // go ahead anyway, to get an exception - case List(m) => - testMethod(m) - case ms => - "cannot disambiguate between multiple implementations of "+f.name - } - } - } -} diff --git a/src/library/scala/text/Document.scala b/src/library/scala/text/Document.scala index b74fd152b5..aa55ac4f0f 100644 --- a/src/library/scala/text/Document.scala +++ b/src/library/scala/text/Document.scala @@ -10,11 +10,17 @@ package scala.text import java.io.Writer +@deprecated("This object will be removed.", "2.11.0") case object DocNil extends Document +@deprecated("This object will be removed.", "2.11.0") case object DocBreak extends Document +@deprecated("This class will be removed.", "2.11.0") case class DocText(txt: String) extends Document +@deprecated("This class will be removed.", "2.11.0") case class DocGroup(doc: Document) extends Document +@deprecated("This class will be removed.", "2.11.0") case class DocNest(indent: Int, doc: Document) extends Document +@deprecated("This class will be removed.", "2.11.0") case class DocCons(hd: Document, tl: Document) extends Document /** @@ -24,6 +30,7 @@ case class DocCons(hd: Document, tl: Document) extends Document * @author Michel Schinz * @version 1.0 */ +@deprecated("This class will be removed.", "2.11.0") abstract class Document { def ::(hd: Document): Document = DocCons(hd, this) def ::(hd: String): Document = DocCons(DocText(hd), this) @@ -80,7 +87,7 @@ abstract class Document { fmt(k, (i + ii, b, d) :: z) case (i, true, DocBreak) :: z => writer write "\n" - spaces(i); + spaces(i) fmt(i, z) case (i, false, DocBreak) :: z => writer write " " @@ -96,6 +103,7 @@ abstract class Document { } } +@deprecated("This object will be removed.", "2.11.0") object Document { /** The empty document */ def empty = DocNil diff --git a/src/library/scala/throws.scala b/src/library/scala/throws.scala index 159f1f02f4..5a5dd9a1f5 100644 --- a/src/library/scala/throws.scala +++ b/src/library/scala/throws.scala @@ -24,5 +24,5 @@ package scala * @since 2.1 */ class throws[T <: Throwable](cause: String = "") extends scala.annotation.StaticAnnotation { - def this(clazz: Class[T]) = this() + def this(clazz: Class[T]) = this("") } diff --git a/src/library/scala/transient.scala b/src/library/scala/transient.scala index 8ff7c582b4..ec87439093 100644 --- a/src/library/scala/transient.scala +++ b/src/library/scala/transient.scala @@ -6,8 +6,6 @@ ** |/ ** \* */ - - package scala import scala.annotation.meta._ diff --git a/src/library/scala/util/DynamicVariable.scala b/src/library/scala/util/DynamicVariable.scala index 52cba6850d..963fe1c497 100644 --- a/src/library/scala/util/DynamicVariable.scala +++ b/src/library/scala/util/DynamicVariable.scala @@ -6,7 +6,8 @@ ** |/ ** \* */ -package scala.util +package scala +package util import java.lang.InheritableThreadLocal diff --git a/src/library/scala/util/Either.scala b/src/library/scala/util/Either.scala index dba11ed73c..b1a932be7e 100644 --- a/src/library/scala/util/Either.scala +++ b/src/library/scala/util/Either.scala @@ -8,7 +8,8 @@ -package scala.util +package scala +package util import scala.language.implicitConversions @@ -21,7 +22,7 @@ import scala.language.implicitConversions * [[scala.util.Right]] takes the place of [[scala.Some]]. Convention dictates * that Left is used for failure and Right is used for success. * - * For example, you could use ``Either[String, Int]`` to detect whether a + * For example, you could use `Either[String, Int]` to detect whether a * received input is a String or an Int. * * {{{ @@ -205,7 +206,7 @@ final case class Right[+A, +B](b: B) extends Either[A, B] { object Either { /** - * Allows use of a ``merge`` method to extract values from Either instances + * Allows use of a `merge` method to extract values from Either instances * regardless of whether they are Left or Right. * * {{{ @@ -215,14 +216,12 @@ object Either { * r.merge: Seq[Int] // Vector(1) * }}} */ - implicit class MergeableEither[A](x: Either[A, A]) { + implicit class MergeableEither[A](private val x: Either[A, A]) extends AnyVal { def merge: A = x match { case Left(a) => a case Right(a) => a } } - @deprecated("use MergeableEither instead", "2.10.0") - def either2mergeable[A](x: Either[A, A]): MergeableEither[A] = new MergeableEither(x) /** * Projects an `Either` into a `Left`. diff --git a/src/library/scala/util/Marshal.scala b/src/library/scala/util/Marshal.scala deleted file mode 100644 index b78ed2140e..0000000000 --- a/src/library/scala/util/Marshal.scala +++ /dev/null @@ -1,50 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2008-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - - -package scala.util - -/** - * Marshalling of Scala objects using Scala tags. - * - * @author Stephane Micheloud - * @version 1.0 - */ -@deprecated("This class will be removed", "2.10.0") -object Marshal { - import java.io._ - import scala.reflect.ClassTag - - def dump[A](o: A)(implicit t: ClassTag[A]): Array[Byte] = { - val ba = new ByteArrayOutputStream(512) - val out = new ObjectOutputStream(ba) - out.writeObject(t) - out.writeObject(o) - out.close() - ba.toByteArray() - } - - @throws(classOf[IOException]) - @throws(classOf[ClassCastException]) - @throws(classOf[ClassNotFoundException]) - def load[A](buffer: Array[Byte])(implicit expected: ClassTag[A]): A = { - val in = new ObjectInputStream(new ByteArrayInputStream(buffer)) - val found = in.readObject.asInstanceOf[ClassTag[_]] - try { - found.runtimeClass.asSubclass(expected.runtimeClass) - in.readObject.asInstanceOf[A] - } catch { - case _: ClassCastException => - in.close() - throw new ClassCastException("type mismatch;"+ - "\n found : "+found+ - "\n required: "+expected) - } - } -} diff --git a/src/library/scala/util/MurmurHash.scala b/src/library/scala/util/MurmurHash.scala index a5bc8faf8d..e05fe0875b 100644 --- a/src/library/scala/util/MurmurHash.scala +++ b/src/library/scala/util/MurmurHash.scala @@ -6,7 +6,8 @@ ** |/ ** \* */ -package scala.util +package scala +package util /** An implementation of Austin Appleby's MurmurHash 3.0 algorithm * (32 bit version); reference: http://code.google.com/p/smhasher @@ -81,6 +82,7 @@ class MurmurHash[@specialized(Int,Long,Float,Double) T](seed: Int) extends (T => * needs to be called to finalize the hash. */ @deprecated("Use the object MurmurHash3 instead.", "2.10.0") +// NOTE: Used by SBT 0.13.0-M2 and below object MurmurHash { // Magic values used for MurmurHash's 32 bit hash. // Don't change these without consulting a hashing expert! @@ -164,13 +166,13 @@ object MurmurHash { var k = hiddenMagicB var j = 0 while (j+1 < s.length) { - val i = (s.charAt(j)<<16) + s.charAt(j+1); + val i = (s.charAt(j)<<16) + s.charAt(j+1) h = extendHash(h,i,c,k) c = nextMagicA(c) k = nextMagicB(k) j += 2 } - if (j < s.length) h = extendHash(h,s.charAt(j),c,k) + if (j < s.length) h = extendHash(h,s.charAt(j).toInt,c,k) finalizeHash(h) } diff --git a/src/library/scala/util/Properties.scala b/src/library/scala/util/Properties.scala index d04e5e48fe..d597feb898 100644 --- a/src/library/scala/util/Properties.scala +++ b/src/library/scala/util/Properties.scala @@ -7,7 +7,8 @@ \* */ -package scala.util +package scala +package util import java.io.{ IOException, PrintWriter } import java.util.jar.Attributes.{ Name => AttributeName } @@ -59,6 +60,8 @@ private[scala] trait PropertiesTrait { def envOrElse(name: String, alt: String) = Option(System getenv name) getOrElse alt def envOrNone(name: String) = Option(System getenv name) + def envOrSome(name: String, alt: Option[String]) = envOrNone(name) orElse alt + // for values based on propFilename def scalaPropOrElse(name: String, alt: String): String = scalaProps.getProperty(name, alt) def scalaPropOrEmpty(name: String): String = scalaPropOrElse(name, "") @@ -128,10 +131,9 @@ private[scala] trait PropertiesTrait { def javaVmName = propOrEmpty("java.vm.name") def javaVmVendor = propOrEmpty("java.vm.vendor") def javaVmVersion = propOrEmpty("java.vm.version") - // this property must remain less-well-known until 2.11 - private def javaSpecVersion = propOrEmpty("java.specification.version") - //private def javaSpecVendor = propOrEmpty("java.specification.vendor") - //private def javaSpecName = propOrEmpty("java.specification.name") + def javaSpecVersion = propOrEmpty("java.specification.version") + def javaSpecVendor = propOrEmpty("java.specification.vendor") + def javaSpecName = propOrEmpty("java.specification.name") def osName = propOrEmpty("os.name") def scalaHome = propOrEmpty("scala.home") def tmpDir = propOrEmpty("java.io.tmpdir") @@ -145,7 +147,10 @@ private[scala] trait PropertiesTrait { // See http://mail.openjdk.java.net/pipermail/macosx-port-dev/2012-November/005148.html for // the reason why we don't follow developer.apple.com/library/mac/#technotes/tn2002/tn2110. /** Returns `true` iff the underlying operating system is a version of Apple Mac OSX. */ - def isMac = osName startsWith "Mac OS X" + def isMac = osName startsWith "Mac OS X" + + /* Some runtime values. */ + private[scala] def isAvian = javaVmName contains "Avian" // This is looking for javac, tools.jar, etc. // Tries JDK_HOME first, then the more common but likely jre JAVA_HOME, @@ -168,7 +173,7 @@ private[scala] trait PropertiesTrait { * isJavaAtLeast("1.6") // true * isJavaAtLeast("1.7") // true * isJavaAtLeast("1.8") // false - * }} + * }}} */ def isJavaAtLeast(version: String): Boolean = { def parts(x: String) = { diff --git a/src/library/scala/util/Random.scala b/src/library/scala/util/Random.scala index 24c4cd7a32..8d68c5be38 100644 --- a/src/library/scala/util/Random.scala +++ b/src/library/scala/util/Random.scala @@ -6,7 +6,8 @@ ** |/ ** \* */ -package scala.util +package scala +package util import scala.collection.mutable.ArrayBuffer import scala.collection.generic.CanBuildFrom @@ -17,7 +18,7 @@ import scala.language.{implicitConversions, higherKinds} * @author Stephane Micheloud * */ -class Random(val self: java.util.Random) { +class Random(val self: java.util.Random) extends AnyRef with Serializable { /** Creates a new random number generator using a single long seed. */ def this(seed: Long) = this(new java.util.Random(seed)) @@ -117,7 +118,7 @@ class Random(val self: java.util.Random) { swap(n - 1, k) } - (bf(xs) ++= buf).result + (bf(xs) ++= buf).result() } /** Returns a Stream of pseudorandomly chosen alphanumeric characters, diff --git a/src/library/scala/util/Sorting.scala b/src/library/scala/util/Sorting.scala index 276e157f55..2e021ad9d9 100644 --- a/src/library/scala/util/Sorting.scala +++ b/src/library/scala/util/Sorting.scala @@ -141,14 +141,14 @@ object Sorting { var done = false while (!done) { while (b <= c && x(b) <= v) { - if (x(b) == v) { + if (x(b) equiv v) { swap(a, b) a += 1 } b += 1 } while (c >= b && x(c) >= v) { - if (x(c) == v) { + if (x(c) equiv v) { swap(c, d) d -= 1 } diff --git a/src/library/scala/util/Try.scala b/src/library/scala/util/Try.scala index 7749543caa..b0cf122f2a 100644 --- a/src/library/scala/util/Try.scala +++ b/src/library/scala/util/Try.scala @@ -6,7 +6,8 @@ ** |/ ** \* */ -package scala.util +package scala +package util import scala.collection.Seq import scala.util.control.NonFatal @@ -110,6 +111,35 @@ sealed abstract class Try[+T] { */ def filter(p: T => Boolean): Try[T] + /** Creates a non-strict filter, which eventually converts this to a `Failure` + * if the predicate is not satisfied. + * + * Note: unlike filter, withFilter does not create a new Try. + * Instead, it restricts the domain of subsequent + * `map`, `flatMap`, `foreach`, and `withFilter` operations. + * + * As Try is a one-element collection, this may be a bit overkill, + * but it's consistent with withFilter on Option and the other collections. + * + * @param p the predicate used to test elements. + * @return an object of class `WithFilter`, which supports + * `map`, `flatMap`, `foreach`, and `withFilter` operations. + * All these operations apply to those elements of this Try + * which satisfy the predicate `p`. + */ + @inline final def withFilter(p: T => Boolean): WithFilter = new WithFilter(p) + + /** We need a whole WithFilter class to honor the "doesn't create a new + * collection" contract even though it seems unlikely to matter much in a + * collection with max size 1. + */ + class WithFilter(p: T => Boolean) { + def map[U](f: T => U): Try[U] = Try.this filter p map f + def flatMap[U](f: T => Try[U]): Try[U] = Try.this filter p flatMap f + def foreach[U](f: T => U): Unit = Try.this filter p foreach f + def withFilter(q: T => Boolean): WithFilter = new WithFilter(x => p(x) && q(x)) + } + /** * Applies the given function `f` if this is a `Failure`, otherwise returns this if this is a `Success`. * This is like `flatMap` for the exception. @@ -164,7 +194,7 @@ object Try { } -final case class Failure[+T](val exception: Throwable) extends Try[T] { +final case class Failure[+T](exception: Throwable) extends Try[T] { def isFailure: Boolean = true def isSuccess: Boolean = false def recoverWith[U >: T](f: PartialFunction[Throwable, Try[U]]): Try[U] = diff --git a/src/library/scala/util/automata/BaseBerrySethi.scala b/src/library/scala/util/automata/BaseBerrySethi.scala deleted file mode 100644 index 3f6f4507a9..0000000000 --- a/src/library/scala/util/automata/BaseBerrySethi.scala +++ /dev/null @@ -1,98 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala.util.automata - -import scala.util.regexp.{ Base } -import scala.collection.{ mutable, immutable } - -// todo: replace global variable pos with acc - -/** This class turns a regular expression over `A` into a - * [[scala.util.automata.NondetWordAutom]] over `A` using the celebrated - * position automata construction (also called ''Berry-Sethi'' or ''Glushkov''). - */ -@deprecated("This class will be removed", "2.10.0") -abstract class BaseBerrySethi { - val lang: Base - import lang.{ Alt, Eps, Meta, RegExp, Sequ, Star } - - protected var pos = 0 - - // results which hold all info for the NondetWordAutomaton - protected var follow: mutable.HashMap[Int, Set[Int]] = _ - - protected var finalTag: Int = _ - - protected var finals: immutable.Map[Int, Int] = _ // final states - - // constants -------------------------- - - final val emptySet: Set[Int] = Set() - - private def doComp(r: RegExp, compFunction: RegExp => Set[Int]) = r match { - case x: Alt => (x.rs map compFirst).foldLeft(emptySet)(_ ++ _) - case Eps => emptySet - case x: Meta => compFunction(x.r) - case x: Sequ => - val (l1, l2) = x.rs span (_.isNullable) - ((l1 ++ (l2 take 1)) map compFunction).foldLeft(emptySet)(_ ++ _) - case Star(t) => compFunction(t) - case _ => throw new IllegalArgumentException("unexpected pattern " + r.getClass) - } - - /** Computes `first(r)` for the word regexp `r`. */ - protected def compFirst(r: RegExp): Set[Int] = doComp(r, compFirst) - - /** Computes `last(r)` for the regexp `r`. */ - protected def compLast(r: RegExp): Set[Int] = doComp(r, compLast) - - /** Starts from the right-to-left - * precondition: pos is final - * pats are successor patterns of a Sequence node - */ - protected def compFollow(rs: Seq[RegExp]): Set[Int] = { - follow(0) = - if (rs.isEmpty) emptySet - else rs.foldRight(Set(pos))((p, fol) => { - val first = compFollow1(fol, p) - - if (p.isNullable) fol ++ first - else first - }) - - follow(0) - } - - /** Returns the first set of an expression, setting the follow set along the way. - */ - protected def compFollow1(fol1: Set[Int], r: RegExp): Set[Int] = r match { - case x: Alt => Set((x.rs reverseMap (compFollow1(fol1, _))).flatten: _*) - case x: Meta => compFollow1(fol1, x.r) - case x: Star => compFollow1(fol1 ++ compFirst(x.r), x.r) - case x: Sequ => - x.rs.foldRight(fol1) { (p, fol) => - val first = compFollow1(fol, p) - - if (p.isNullable) fol ++ first - else first - } - case _ => throw new IllegalArgumentException("unexpected pattern: " + r.getClass) - } - - /** Returns the "Sethi-length" of a pattern, creating the set of position along the way. - */ - protected def traverse(r: RegExp): Unit = r match { - // (is tree automaton stuff, more than Berry-Sethi) - case x: Alt => x.rs foreach traverse - case x: Sequ => x.rs foreach traverse - case x: Meta => traverse(x.r) - case Star(t) => traverse(t) - case _ => throw new IllegalArgumentException("unexp pattern " + r.getClass) - } -} diff --git a/src/library/scala/util/automata/DetWordAutom.scala b/src/library/scala/util/automata/DetWordAutom.scala deleted file mode 100644 index 5d709106f8..0000000000 --- a/src/library/scala/util/automata/DetWordAutom.scala +++ /dev/null @@ -1,49 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala.util.automata - -import scala.collection.{ mutable, immutable } - -/** A deterministic automaton. States are integers, where - * 0 is always the only initial state. Transitions are represented - * in the delta function. A default transitions is one that - * is taken when no other transition can be taken. - * All states are reachable. Accepting states are those for which - * the partial function 'finals' is defined. - * - * @author Burak Emir - * @version 1.0 - */ -@deprecated("This class will be removed", "2.10.0") -abstract class DetWordAutom[T <: AnyRef] { - val nstates: Int - val finals: Array[Int] - val delta: Array[mutable.Map[T, Int]] - val default: Array[Int] - - def isFinal(q: Int) = finals(q) != 0 - def isSink(q: Int) = delta(q).isEmpty && default(q) == q - def next(q: Int, label: T) = delta(q).getOrElse(label, default(q)) - - override def toString() = { - val sb = new StringBuilder("[DetWordAutom nstates=") - sb.append(nstates) - sb.append(" finals=") - val map = Map(finals.zipWithIndex map (_.swap): _*) - sb.append(map.toString()) - sb.append(" delta=\n") - - for (i <- 0 until nstates) { - sb append "%d->%s\n".format(i, delta(i)) - if (i < default.length) - sb append "_>%s\n".format(default(i)) - } - sb.toString - } -} diff --git a/src/library/scala/util/automata/Inclusion.scala b/src/library/scala/util/automata/Inclusion.scala deleted file mode 100644 index 91441bd3a8..0000000000 --- a/src/library/scala/util/automata/Inclusion.scala +++ /dev/null @@ -1,69 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - - -package scala.util.automata - - -/** A fast test of language inclusion between minimal automata. - * inspired by the ''AMoRE automata library''. - * - * @author Burak Emir - * @version 1.0 - */ -@deprecated("This class will be removed", "2.10.0") -trait Inclusion[A <: AnyRef] { - - val labels: Seq[A] - - /** Returns true if `dfa1` is included in `dfa2`. - */ - def inclusion(dfa1: DetWordAutom[A], dfa2: DetWordAutom[A]) = { - - def encode(q1: Int, q2: Int) = 1 + q1 + q2 * dfa1.nstates - def decode2(c: Int) = (c-1) / (dfa1.nstates) //integer division - def decode1(c: Int) = (c-1) % (dfa1.nstates) - - var q1 = 0 //dfa1.initstate; // == 0 - var q2 = 0 //dfa2.initstate; // == 0 - - val max = 1 + dfa1.nstates * dfa2.nstates - val mark = new Array[Int](max) - - var result = true - var current = encode(q1, q2) - var last = current - mark(last) = max // mark (q1,q2) - while (current != 0 && result) { - //Console.println("current = [["+q1+" "+q2+"]] = "+current); - for (letter <- labels) { - val r1 = dfa1.next(q1,letter) - val r2 = dfa2.next(q2,letter) - if (dfa1.isFinal(r1) && !dfa2.isFinal(r2)) - result = false - val test = encode(r1, r2) - //Console.println("test = [["+r1+" "+r2+"]] = "+test); - if (mark(test) == 0) { - mark(last) = test - mark(test) = max - last = test - } - } - val ncurrent = mark(current) - if( ncurrent != max ) { - q1 = decode1(ncurrent) - q2 = decode2(ncurrent) - current = ncurrent - } else { - current = 0 - } - } - result - } -} diff --git a/src/library/scala/util/automata/NondetWordAutom.scala b/src/library/scala/util/automata/NondetWordAutom.scala deleted file mode 100644 index 24c6612d0f..0000000000 --- a/src/library/scala/util/automata/NondetWordAutom.scala +++ /dev/null @@ -1,59 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala.util.automata - -import scala.collection.{ immutable, mutable } - -/** A nondeterministic automaton. States are integers, where - * 0 is always the only initial state. Transitions are represented - * in the delta function. Default transitions are transitions that - * are taken when no other transitions can be applied. - * All states are reachable. Accepting states are those for which - * the partial function `finals` is defined. - */ -@deprecated("This class will be removed", "2.10.0") -abstract class NondetWordAutom[T <: AnyRef] { - val nstates: Int - val labels: Seq[T] - val finals: Array[Int] // 0 means not final - val delta: Array[mutable.Map[T, immutable.BitSet]] - val default: Array[immutable.BitSet] - - /** @return true if the state is final */ - final def isFinal(state: Int) = finals(state) > 0 - - /** @return tag of final state */ - final def finalTag(state: Int) = finals(state) - - /** @return true if the set of states contains at least one final state */ - final def containsFinal(Q: immutable.BitSet): Boolean = Q exists isFinal - - /** @return true if there are no accepting states */ - final def isEmpty = (0 until nstates) forall (x => !isFinal(x)) - - /** @return a immutable.BitSet with the next states for given state and label */ - def next(q: Int, a: T): immutable.BitSet = delta(q).getOrElse(a, default(q)) - - /** @return a immutable.BitSet with the next states for given state and label */ - def next(Q: immutable.BitSet, a: T): immutable.BitSet = next(Q, next(_, a)) - def nextDefault(Q: immutable.BitSet): immutable.BitSet = next(Q, default) - - private def next(Q: immutable.BitSet, f: (Int) => immutable.BitSet): immutable.BitSet = - (Q map f).foldLeft(immutable.BitSet.empty)(_ ++ _) - - private def finalStates = 0 until nstates filter isFinal - override def toString = { - - val finalString = Map(finalStates map (j => j -> finals(j)) : _*).toString - val deltaString = (0 until nstates) - .map(i => " %d->%s\n _>%s\n".format(i, delta(i), default(i))).mkString - - "[NondetWordAutom nstates=%d finals=%s delta=\n%s".format(nstates, finalString, deltaString) - } -} diff --git a/src/library/scala/util/automata/SubsetConstruction.scala b/src/library/scala/util/automata/SubsetConstruction.scala deleted file mode 100644 index 0ee768587c..0000000000 --- a/src/library/scala/util/automata/SubsetConstruction.scala +++ /dev/null @@ -1,107 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala.util.automata - -import scala.collection.{ mutable, immutable } - -@deprecated("This class will be removed", "2.10.0") -class SubsetConstruction[T <: AnyRef](val nfa: NondetWordAutom[T]) { - import nfa.labels - - def selectTag(Q: immutable.BitSet, finals: Array[Int]) = - (Q map finals filter (_ > 0)).min - - def determinize: DetWordAutom[T] = { - // for assigning numbers to bitsets - var indexMap = scala.collection.Map[immutable.BitSet, Int]() - var invIndexMap = scala.collection.Map[Int, immutable.BitSet]() - var ix = 0 - - // we compute the dfa with states = bitsets - val q0 = immutable.BitSet(0) // the set { 0 } - val sink = immutable.BitSet.empty // the set { } - - var states = Set(q0, sink) // initial set of sets - val delta = new mutable.HashMap[immutable.BitSet, mutable.HashMap[T, immutable.BitSet]] - var deftrans = mutable.Map(q0 -> sink, sink -> sink) // initial transitions - var finals: mutable.Map[immutable.BitSet, Int] = mutable.Map() - val rest = new mutable.Stack[immutable.BitSet] - - rest.push(sink, q0) - - def addFinal(q: immutable.BitSet) { - if (nfa containsFinal q) - finals = finals.updated(q, selectTag(q, nfa.finals)) - } - def add(Q: immutable.BitSet) { - if (!states(Q)) { - states += Q - rest push Q - addFinal(Q) - } - } - - addFinal(q0) // initial state may also be a final state - - while (!rest.isEmpty) { - val P = rest.pop - // assign a number to this bitset - indexMap = indexMap.updated(P, ix) - invIndexMap = invIndexMap.updated(ix, P) - ix += 1 - - // make transition map - val Pdelta = new mutable.HashMap[T, immutable.BitSet] - delta.update(P, Pdelta) - - labels foreach { label => - val Q = nfa.next(P, label) - Pdelta.update(label, Q) - add(Q) - } - - // collect default transitions - val Pdef = nfa nextDefault P - deftrans = deftrans.updated(P, Pdef) - add(Pdef) - } - - // create DetWordAutom, using indices instead of sets - val nstatesR = states.size - val deltaR = new Array[mutable.Map[T, Int]](nstatesR) - val defaultR = new Array[Int](nstatesR) - val finalsR = new Array[Int](nstatesR) - - for (Q <- states) { - val q = indexMap(Q) - val trans = delta(Q) - val transDef = deftrans(Q) - val qDef = indexMap(transDef) - val ntrans = new mutable.HashMap[T, Int]() - - for ((label, value) <- trans) { - val p = indexMap(value) - if (p != qDef) - ntrans.update(label, p) - } - - deltaR(q) = ntrans - defaultR(q) = qDef - } - - finals foreach { case (k,v) => finalsR(indexMap(k)) = v } - - new DetWordAutom [T] { - val nstates = nstatesR - val delta = deltaR - val default = defaultR - val finals = finalsR - } - } -} diff --git a/src/library/scala/util/automata/WordBerrySethi.scala b/src/library/scala/util/automata/WordBerrySethi.scala deleted file mode 100644 index 12448f595d..0000000000 --- a/src/library/scala/util/automata/WordBerrySethi.scala +++ /dev/null @@ -1,164 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala.util.automata - -import scala.collection.{ immutable, mutable } -import scala.util.regexp.WordExp - -/** This class turns a regular expression into a [[scala.util.automata.NondetWordAutom]] - * celebrated position automata construction (also called ''Berry-Sethi'' or ''Glushkov''). - * - * @author Burak Emir - * @version 1.0 - */ -@deprecated("This class will be removed", "2.10.0") -abstract class WordBerrySethi extends BaseBerrySethi { - override val lang: WordExp - - import lang.{ Alt, Eps, Letter, Meta, RegExp, Sequ, Star, _labelT } - - protected var labels: mutable.HashSet[_labelT] = _ - // don't let this fool you, only labelAt is a real, surjective mapping - protected var labelAt: Map[Int, _labelT] = _ // new alphabet "gamma" - protected var deltaq: Array[mutable.HashMap[_labelT, List[Int]]] = _ // delta - protected var defaultq: Array[List[Int]] = _ // default transitions - protected var initials: Set[Int] = _ - - /** Computes `first(r)` where the word regexp `r`. - * - * @param r the regular expression - * @return the computed set `first(r)` - */ - protected override def compFirst(r: RegExp): Set[Int] = r match { - case x: Letter => Set(x.pos) - case _ => super.compFirst(r) - } - - /** Computes `last(r)` where the word regexp `r`. - * - * @param r the regular expression - * @return the computed set `last(r)` - */ - protected override def compLast(r: RegExp): Set[Int] = r match { - case x: Letter => Set(x.pos) - case _ => super.compLast(r) - } - - /** Returns the first set of an expression, setting the follow set along - * the way. - * - * @param r the regular expression - * @return the computed set - */ - protected override def compFollow1(fol1: Set[Int], r: RegExp): Set[Int] = r match { - case x: Letter => follow(x.pos) = fol1 ; Set(x.pos) - case Eps => emptySet - case _ => super.compFollow1(fol1, r) - } - - /** Returns "Sethi-length" of a pattern, creating the set of position - * along the way - */ - - /** Called at the leaves of the regexp */ - protected def seenLabel(r: RegExp, i: Int, label: _labelT) { - labelAt = labelAt.updated(i, label) - this.labels += label - } - - // overridden in BindingBerrySethi - protected def seenLabel(r: RegExp, label: _labelT): Int = { - pos += 1 - seenLabel(r, pos, label) - pos - } - - // todo: replace global variable pos with acc - override def traverse(r: RegExp): Unit = r match { - case a @ Letter(label) => a.pos = seenLabel(r, label) - case Eps => // ignore - case _ => super.traverse(r) - } - - - protected def makeTransition(src: Int, dest: Int, label: _labelT) { - val q = deltaq(src) - q.update(label, dest :: q.getOrElse(label, Nil)) - } - - protected def initialize(subexpr: Seq[RegExp]): Unit = { - this.labelAt = immutable.Map() - this.follow = mutable.HashMap() - this.labels = mutable.HashSet() - this.pos = 0 - - // determine "Sethi-length" of the regexp - subexpr foreach traverse - - this.initials = Set(0) - } - - protected def initializeAutom() { - finals = immutable.Map.empty[Int, Int] // final states - deltaq = new Array[mutable.HashMap[_labelT, List[Int]]](pos) // delta - defaultq = new Array[List[Int]](pos) // default transitions - - for (j <- 0 until pos) { - deltaq(j) = mutable.HashMap[_labelT, List[Int]]() - defaultq(j) = Nil - } - } - - protected def collectTransitions(): Unit = // make transitions - for (j <- 0 until pos ; fol = follow(j) ; k <- fol) { - if (pos == k) finals = finals.updated(j, finalTag) - else makeTransition(j, k, labelAt(k)) - } - - def automatonFrom(pat: RegExp, finalTag: Int): NondetWordAutom[_labelT] = { - this.finalTag = finalTag - - pat match { - case x: Sequ => - // (1,2) compute follow + first - initialize(x.rs) - pos += 1 - compFollow(x.rs) // this used to be assigned to var globalFirst and then never used. - - // (3) make automaton from follow sets - initializeAutom() - collectTransitions() - - if (x.isNullable) // initial state is final - finals = finals.updated(0, finalTag) - - val delta1 = immutable.Map(deltaq.zipWithIndex map (_.swap): _*) - val finalsArr = (0 until pos map (k => finals.getOrElse(k, 0))).toArray // 0 == not final - val initialsArr = initials.toArray - - val deltaArr: Array[mutable.Map[_labelT, immutable.BitSet]] = - (0 until pos map { x => - mutable.HashMap(delta1(x).toSeq map { case (k, v) => k -> immutable.BitSet(v: _*) } : _*) - }).toArray - - val defaultArr = (0 until pos map (k => immutable.BitSet(defaultq(k): _*))).toArray - - new NondetWordAutom[_labelT] { - val nstates = pos - val labels = WordBerrySethi.this.labels.toList - val initials = initialsArr - val finals = finalsArr - val delta = deltaArr - val default = defaultArr - } - case z => - automatonFrom(Sequ(z.asInstanceOf[this.lang._regexpT]), finalTag) - } - } -} diff --git a/src/library/scala/util/control/Breaks.scala b/src/library/scala/util/control/Breaks.scala index 89e1b58d95..5524b10afa 100644 --- a/src/library/scala/util/control/Breaks.scala +++ b/src/library/scala/util/control/Breaks.scala @@ -6,7 +6,8 @@ ** |/ ** \* */ -package scala.util.control +package scala +package util.control /** A class that can be instantiated for the break control abstraction. * Example usage: diff --git a/src/library/scala/util/control/ControlThrowable.scala b/src/library/scala/util/control/ControlThrowable.scala index 33c90c5815..7ed3d95cd3 100644 --- a/src/library/scala/util/control/ControlThrowable.scala +++ b/src/library/scala/util/control/ControlThrowable.scala @@ -6,7 +6,8 @@ ** |/ ** \* */ -package scala.util.control +package scala +package util.control /** A marker trait indicating that the `Throwable` it is mixed into is * intended for flow control. diff --git a/src/library/scala/util/control/Exception.scala b/src/library/scala/util/control/Exception.scala index b97914c4b1..be6d03a145 100644 --- a/src/library/scala/util/control/Exception.scala +++ b/src/library/scala/util/control/Exception.scala @@ -6,7 +6,8 @@ ** |/ ** \* */ -package scala.util +package scala +package util package control import scala.collection.immutable.List diff --git a/src/library/scala/util/control/NonFatal.scala b/src/library/scala/util/control/NonFatal.scala index 0d8cdfbace..9d3dfea074 100644 --- a/src/library/scala/util/control/NonFatal.scala +++ b/src/library/scala/util/control/NonFatal.scala @@ -6,13 +6,13 @@ ** |/ ** \* */ -package scala.util.control +package scala +package util.control /** * Extractor of non-fatal Throwables. Will not match fatal errors like `VirtualMachineError` - * (for example, `OutOfMemoryError`, a subclass of `VirtualMachineError`), `ThreadDeath`, - * `LinkageError`, `InterruptedException`, `ControlThrowable`, or `NotImplementedError`. - * However, `StackOverflowError` is matched, i.e. considered non-fatal. + * (for example, `OutOfMemoryError` and `StackOverflowError`, subclasses of `VirtualMachineError`), `ThreadDeath`, + * `LinkageError`, `InterruptedException`, `ControlThrowable`. * * Note that [[scala.util.control.ControlThrowable]], an internal Throwable, is not matched by * `NonFatal` (and would therefore be thrown). @@ -33,9 +33,8 @@ object NonFatal { * Returns true if the provided `Throwable` is to be considered non-fatal, or false if it is to be considered fatal */ def apply(t: Throwable): Boolean = t match { - case _: StackOverflowError => true // StackOverflowError ok even though it is a VirtualMachineError // VirtualMachineError includes OutOfMemoryError and other fatal errors - case _: VirtualMachineError | _: ThreadDeath | _: InterruptedException | _: LinkageError | _: ControlThrowable | _: NotImplementedError => false + case _: VirtualMachineError | _: ThreadDeath | _: InterruptedException | _: LinkageError | _: ControlThrowable => false case _ => true } /** diff --git a/src/library/scala/util/control/TailCalls.scala b/src/library/scala/util/control/TailCalls.scala index 955cee7657..953d5b407e 100644 --- a/src/library/scala/util/control/TailCalls.scala +++ b/src/library/scala/util/control/TailCalls.scala @@ -6,13 +6,18 @@ ** |/ ** \* */ -package scala.util.control +package scala +package util.control /** Methods exported by this object implement tail calls via trampolining. * Tail calling methods have to return their result using `done` or call the * next method using `tailcall`. Both return a `TailRec` object. The result * of evaluating a tailcalling function can be retrieved from a `Tailrec` - * value using method `result`. Here's a usage example: + * value using method `result`. + * Implemented as described in "Stackless Scala with Free Monads" + * http://blog.higher-order.com/assets/trampolines.pdf + * + * Here's a usage example: * {{{ * import scala.util.control.TailCalls._ * @@ -23,6 +28,14 @@ package scala.util.control * if (xs.isEmpty) done(false) else tailcall(isEven(xs.tail)) * * isEven((1 to 100000).toList).result + * + * def fib(n: Int): TailRec[Int] = + * if (n < 2) done(n) else for { + * x <- tailcall(fib(n - 1)) + * y <- tailcall(fib(n - 2)) + * } yield (x + y) + * + * fib(40).result * }}} */ object TailCalls { @@ -30,14 +43,43 @@ object TailCalls { /** This class represents a tailcalling computation */ abstract class TailRec[+A] { + + /** Continue the computation with `f`. */ + final def map[B](f: A => B): TailRec[B] = + flatMap(a => Call(() => Done(f(a)))) + + /** Continue the computation with `f` and merge the trampolining + * of this computation with that of `f`. */ + final def flatMap[B](f: A => TailRec[B]): TailRec[B] = + this match { + case Done(a) => Call(() => f(a)) + case c@Call(_) => Cont(c, f) + // Take advantage of the monad associative law to optimize the size of the required stack + case c: Cont[a1, b1] => Cont(c.a, (x: a1) => c f x flatMap f) + } + + /** Returns either the next step of the tailcalling computation, + * or the result if there are no more steps. */ + @annotation.tailrec final def resume: Either[() => TailRec[A], A] = this match { + case Done(a) => Right(a) + case Call(k) => Left(k) + case Cont(a, f) => a match { + case Done(v) => f(v).resume + case Call(k) => Left(() => k().flatMap(f)) + case Cont(b, g) => b.flatMap(x => g(x) flatMap f).resume + } + } + /** Returns the result of the tailcalling computation. */ - def result: A = { - def loop(body: TailRec[A]): A = body match { - case Call(rest) => loop(rest()) - case Done(result) => result + @annotation.tailrec final def result: A = this match { + case Done(a) => a + case Call(t) => t().result + case Cont(a, f) => a match { + case Done(v) => f(v).result + case Call(t) => t().flatMap(f).result + case Cont(b, g) => b.flatMap(x => g(x) flatMap f).result } - loop(this) } } @@ -46,19 +88,23 @@ object TailCalls { /** Internal class representing the final result returned from a tailcalling * computation */ - protected case class Done[A](override val result: A) extends TailRec[A] + protected case class Done[A](value: A) extends TailRec[A] + + /** Internal class representing a continuation with function A => TailRec[B]. + * It is needed for the flatMap to be implemented. */ + protected case class Cont[A, B](a: TailRec[A], f: A => TailRec[B]) extends TailRec[B] /** Performs a tailcall * @param rest the expression to be evaluated in the tailcall * @return a `TailRec` object representing the expression `rest` */ - def tailcall[A](rest: => TailRec[A]): TailRec[A] = new Call(() => rest) + def tailcall[A](rest: => TailRec[A]): TailRec[A] = Call(() => rest) /** Used to return final result from tailcalling computation * @param `result` the result value * @return a `TailRec` object representing a computation which immediately * returns `result` */ - def done[A](result: A): TailRec[A] = new Done(result) + def done[A](result: A): TailRec[A] = Done(result) } diff --git a/src/library/scala/util/grammar/HedgeRHS.scala b/src/library/scala/util/grammar/HedgeRHS.scala deleted file mode 100644 index d1c11a2f99..0000000000 --- a/src/library/scala/util/grammar/HedgeRHS.scala +++ /dev/null @@ -1,26 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - - -package scala.util.grammar - -@deprecated("This class will be removed", "2.10.0") -abstract class HedgeRHS - -/** Right hand side of a hedge production, deriving a single tree. */ -@deprecated("This class will be removed", "2.10.0") -case class ConsRHS(tnt: Int, hnt: Int) extends HedgeRHS - -/** Right hand side of a hedge production, deriving any hedge. */ -@deprecated("This class will be removed", "2.10.0") -case object AnyHedgeRHS extends HedgeRHS - -/** Right hand side of a hedge production, deriving the empty hedge. */ -@deprecated("This class will be removed", "2.10.0") -case object EmptyHedgeRHS extends HedgeRHS diff --git a/src/library/scala/util/grammar/TreeRHS.scala b/src/library/scala/util/grammar/TreeRHS.scala deleted file mode 100644 index ee72ea982d..0000000000 --- a/src/library/scala/util/grammar/TreeRHS.scala +++ /dev/null @@ -1,22 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - - -package scala.util.grammar - -/** Right hand side of a tree production. */ -@deprecated("This class will be removed", "2.10.0") -abstract class TreeRHS - -/** Right hand side of a tree production, labelled with a letter from an alphabet. */ -@deprecated("This class will be removed", "2.10.0") -case class LabelledRHS[A](label: A, hnt: Int) extends TreeRHS - -@deprecated("This class will be removed", "2.10.0") -case object AnyTreeRHS extends TreeRHS diff --git a/src/library/scala/util/hashing/ByteswapHashing.scala b/src/library/scala/util/hashing/ByteswapHashing.scala index a96945788c..470479725b 100644 --- a/src/library/scala/util/hashing/ByteswapHashing.scala +++ b/src/library/scala/util/hashing/ByteswapHashing.scala @@ -6,7 +6,8 @@ ** |/ ** \* */ -package scala.util.hashing +package scala +package util.hashing @@ -16,20 +17,20 @@ package scala.util.hashing /** A fast multiplicative hash by Phil Bagwell. */ final class ByteswapHashing[T] extends Hashing[T] { - + def hash(v: T) = byteswap32(v.##) - + } object ByteswapHashing { - + private class Chained[T](h: Hashing[T]) extends Hashing[T] { def hash(v: T) = byteswap32(h.hash(v)) } - + /** Composes another `Hashing` with the Byteswap hash. */ def chain[T](h: Hashing[T]): Hashing[T] = new Chained(h) - + } diff --git a/src/library/scala/util/hashing/Hashing.scala b/src/library/scala/util/hashing/Hashing.scala index b57f858bed..2b72c1dbe3 100644 --- a/src/library/scala/util/hashing/Hashing.scala +++ b/src/library/scala/util/hashing/Hashing.scala @@ -6,7 +6,8 @@ ** |/ ** \* */ -package scala.util.hashing +package scala +package util.hashing import scala.annotation.implicitNotFound diff --git a/src/library/scala/util/hashing/MurmurHash3.scala b/src/library/scala/util/hashing/MurmurHash3.scala index 0aa7e6f1cb..1bfaeb255b 100644 --- a/src/library/scala/util/hashing/MurmurHash3.scala +++ b/src/library/scala/util/hashing/MurmurHash3.scala @@ -6,7 +6,8 @@ ** |/ ** \* */ -package scala.util.hashing +package scala +package util.hashing import java.lang.Integer.{ rotateLeft => rotl } @@ -76,7 +77,7 @@ private[hashing] class MurmurHash3 { h = mix(h, data) i += 2 } - if (i < str.length) h = mixLast(h, str.charAt(i)) + if (i < str.length) h = mixLast(h, str.charAt(i).toInt) finalizeHash(h, str.length) } @@ -274,12 +275,4 @@ object MurmurHash3 extends MurmurHash3 { finalizeHash(h, n) } */ - - @deprecated("Use unorderedHash", "2.10.0") - final def symmetricHash[T](xs: scala.collection.GenTraversableOnce[T], seed: Int = symmetricSeed): Int = - unorderedHash(xs.seq, seed) - - @deprecated("Use orderedHash", "2.10.0") - final def traversableHash[T](xs: scala.collection.GenTraversableOnce[T], seed: Int = traversableSeed): Int = - orderedHash(xs.seq, seed) } diff --git a/src/library/scala/util/hashing/package.scala b/src/library/scala/util/hashing/package.scala index 7d38f151f9..2c8e0154fc 100644 --- a/src/library/scala/util/hashing/package.scala +++ b/src/library/scala/util/hashing/package.scala @@ -6,7 +6,8 @@ ** |/ ** \* */ -package scala.util +package scala +package util @@ -14,7 +15,7 @@ package scala.util package object hashing { - + /** Fast multiplicative hash with a nice distribution. */ def byteswap32(v: Int): Int = { @@ -22,7 +23,7 @@ package object hashing { hc = java.lang.Integer.reverseBytes(hc) hc * 0x9e3775cd } - + /** Fast multiplicative hash with a nice distribution * for 64-bit values. */ @@ -31,5 +32,5 @@ package object hashing { hc = java.lang.Long.reverseBytes(hc) hc * 0x9e3775cd9e3775cdL } - + } diff --git a/src/library/scala/util/logging/ConsoleLogger.scala b/src/library/scala/util/logging/ConsoleLogger.scala deleted file mode 100644 index 74f058b4ec..0000000000 --- a/src/library/scala/util/logging/ConsoleLogger.scala +++ /dev/null @@ -1,26 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - - -package scala.util.logging - -/** - * The trait `ConsoleLogger` is mixed into a concrete class who - * has class `Logged` among its base classes. - * - * @author Burak Emir - * @version 1.0 - */ -@deprecated("This class will be removed.", "2.10.0") -trait ConsoleLogger extends Logged { - - /** logs argument to Console using [[scala.Console.println]] - */ - override def log(msg: String): Unit = Console.println(msg) -} diff --git a/src/library/scala/util/logging/Logged.scala b/src/library/scala/util/logging/Logged.scala deleted file mode 100644 index f2661d3206..0000000000 --- a/src/library/scala/util/logging/Logged.scala +++ /dev/null @@ -1,33 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala.util.logging - -/** Mixing in Logged indicates that a class provides support for logging. - * - * For instance: - * {{{ - * // The developer of the library writes: - * class MyClass extends Logged { - * // do stuff, call log - * } - * - * // The user of the library instantiates: - * val x = new MyClass() with ConsoleLogger - * }}} - * and the logging is sent to the [[scala.util.logging.ConsoleLogger]] object. - */ -@deprecated("This class will be removed.", "2.10.0") -trait Logged { - /** This method should log the message given as argument somewhere - * as a side-effect. - * - * @param msg message to be logged - */ - def log(msg: String): Unit = {} -} diff --git a/src/library/scala/util/matching/Regex.scala b/src/library/scala/util/matching/Regex.scala index 716d746552..6743b9e42a 100644 --- a/src/library/scala/util/matching/Regex.scala +++ b/src/library/scala/util/matching/Regex.scala @@ -28,7 +28,8 @@ * into a [[java.lang.String]]. * */ -package scala.util.matching +package scala +package util.matching import scala.collection.AbstractIterator import java.util.regex.{ Pattern, Matcher } @@ -66,7 +67,21 @@ import java.util.regex.{ Pattern, Matcher } * Regex, such as `findFirstIn` or `findAllIn`, or using it as an extractor in a * pattern match. * - * Note, however, that when Regex is used as an extractor in a pattern match, it + * Note that, when calling `findAllIn`, the resulting [[scala.util.matching.Regex.MatchIterator]] + * needs to be initialized (by calling `hasNext` or `next()`, or causing these to be + * called) before information about a match can be retrieved: + * + * {{{ + * val msg = "I love Scala" + * + * // val start = " ".r.findAllIn(msg).start // throws an IllegalStateException + * + * val matches = " ".r.findAllIn(msg) + * matches.hasNext // initializes the matcher + * val start = matches.start + * }}} + * + * When Regex is used as an extractor in a pattern match, note that it * only succeeds if the whole text can be matched. For this reason, one usually * calls a method to find the matching substrings, and then use it as an extractor * to break match into subgroups. @@ -131,7 +146,7 @@ import java.util.regex.{ Pattern, Matcher } * @author Martin Odersky * @version 1.1, 29/01/2008 * - * @param regex A string representing a regular expression + * @param pattern The compiled pattern * @param groupNames A mapping from names to indices in capture groups * * @define replacementString @@ -144,49 +159,119 @@ import java.util.regex.{ Pattern, Matcher } * to automatically escape these characters. */ @SerialVersionUID(-2094783597747625537L) -class Regex(regex: String, groupNames: String*) extends Serializable { +class Regex private[matching](val pattern: Pattern, groupNames: String*) extends Serializable { outer => import Regex._ - /** The compiled pattern */ - val pattern = Pattern.compile(regex) + /** + * @param regex A string representing a regular expression + * @param groupNames A mapping from names to indices in capture groups + */ + def this(regex: String, groupNames: String*) = this(Pattern.compile(regex), groupNames: _*) - /** Tries to match target (whole match) and returns the matching subgroups. - * if the pattern has no subgroups, then it returns an empty list on a - * successful match. - * - * Note, however, that if some subgroup has not been matched, a `null` will - * be returned for that subgroup. + /** Tries to match a [[java.lang.CharSequence]]. + * If the match succeeds, the result is a list of the matching + * groups (or a `null` element if a group did not match any input). + * If the pattern specifies no groups, then the result will be an empty list + * on a successful match. * + * This method attempts to match the entire input by default; to find the next + * matching subsequence, use an unanchored Regex. + * For example: * * {{{ * val p1 = "ab*c".r - * val p2 = "a(b*)c".r - * * val p1Matches = "abbbc" match { * case p1() => true * case _ => false * } - * + * val p2 = "a(b*)c".r * val numberOfB = "abbbc" match { * case p2(b) => Some(b.length) * case _ => None * } + * val p3 = "b*".r.unanchored + * val p3Matches = "abbbc" match { + * case p3() => true + * case _ => false + * } * }}} * + * @param s The string to match + * @return The matches + */ + def unapplySeq(s: CharSequence): Option[List[String]] = { + val m = pattern matcher s + if (runMatcher(m)) Some((1 to m.groupCount).toList map m.group) + else None + } + + /** Tries to match the String representation of a [[scala.Char]]. + * If the match succeeds, the result is the first matching + * group if any groups are defined, or an empty Sequence otherwise. + * + * For example: + * + * {{{ + * val cat = "cat" + * // the case must consume the group to match + * val r = """(\p{Lower})""".r + * cat(0) match { case r(x) => true } + * cat(0) match { case r(_) => true } + * cat(0) match { case r(_*) => true } + * cat(0) match { case r() => true } // no match + * + * // there is no group to extract + * val r = """\p{Lower}""".r + * cat(0) match { case r(x) => true } // no match + * cat(0) match { case r(_) => true } // no match + * cat(0) match { case r(_*) => true } // matches + * cat(0) match { case r() => true } // matches + * + * // even if there are multiple groups, only one is returned + * val r = """((.))""".r + * cat(0) match { case r(_) => true } // matches + * cat(0) match { case r(_,_) => true } // no match + * }}} + * + * @param c The Char to match + * @return The match + */ + def unapplySeq(c: Char): Option[List[Char]] = { + val m = pattern matcher c.toString + if (runMatcher(m)) { + if (m.groupCount > 0) Some((m group 1).toList) else Some(Nil) + } else None + } + + /** Tries to match on a [[scala.util.matching.Regex.Match]]. + * A previously failed match results in None. + * If a successful match was made against the current pattern, then that result is used. + * Otherwise, this Regex is applied to the previously matched input, + * and the result of that match is used. + */ + def unapplySeq(m: Match): Option[List[String]] = + if (m.matched == null) None + else if (m.matcher.pattern == this.pattern) Some((1 to m.groupCount).toList map m.group) + else unapplySeq(m.matched) + + /** Tries to match target. * @param target The string to match * @return The matches */ + @deprecated("Extracting a match result from anything but a CharSequence or Match is deprecated", "2.11.0") def unapplySeq(target: Any): Option[List[String]] = target match { case s: CharSequence => val m = pattern matcher s if (runMatcher(m)) Some((1 to m.groupCount).toList map m.group) else None - case m: Match => unapplySeq(m.matched) - case _ => None + case m: Match => unapplySeq(m.matched) + case _ => None } + + // @see UnanchoredRegex protected def runMatcher(m: Matcher) = m.matches() /** Return all matches of this regexp in given character sequence as a [[scala.util.matching.Regex.MatchIterator]], @@ -196,11 +281,15 @@ class Regex(regex: String, groupNames: String*) extends Serializable { * that can be queried for data such as the text that precedes the * match, subgroups, etc. * + * Attempting to retrieve information about a match before initializing + * the iterator can result in [[java.lang.IllegalStateException]]s. See + * [[scala.util.matching.Regex.MatchIterator]] for details. + * * @param source The text to match against. * @return A [[scala.util.matching.Regex.MatchIterator]] of all matches. * @example {{{for (words <- """\w+""".r findAllIn "A simple example.") yield words}}} */ - def findAllIn(source: java.lang.CharSequence) = new Regex.MatchIterator(source, this, groupNames) + def findAllIn(source: CharSequence) = new Regex.MatchIterator(source, this, groupNames) /** Return all matches of this regexp in given character sequence as a @@ -210,12 +299,12 @@ class Regex(regex: String, groupNames: String*) extends Serializable { * @return A [[scala.collection.Iterator]] of [[scala.util.matching.Regex.Match]] for all matches. * @example {{{for (words <- """\w+""".r findAllMatchIn "A simple example.") yield words.start}}} */ - def findAllMatchIn(source: java.lang.CharSequence): Iterator[Match] = { + def findAllMatchIn(source: CharSequence): Iterator[Match] = { val matchIterator = findAllIn(source) new Iterator[Match] { def hasNext = matchIterator.hasNext def next: Match = { - matchIterator.next; + matchIterator.next() new Match(matchIterator.source, matchIterator.matcher, matchIterator.groupNames).force } } @@ -228,7 +317,7 @@ class Regex(regex: String, groupNames: String*) extends Serializable { * @return An [[scala.Option]] of the first matching string in the text. * @example {{{"""\w+""".r findFirstIn "A simple example." foreach println // prints "A"}}} */ - def findFirstIn(source: java.lang.CharSequence): Option[String] = { + def findFirstIn(source: CharSequence): Option[String] = { val m = pattern.matcher(source) if (m.find) Some(m.group) else None } @@ -245,7 +334,7 @@ class Regex(regex: String, groupNames: String*) extends Serializable { * @return A [[scala.Option]] of [[scala.util.matching.Regex.Match]] of the first matching string in the text. * @example {{{("""[a-z]""".r findFirstMatchIn "A simple example.") map (_.start) // returns Some(2), the index of the first match in the text}}} */ - def findFirstMatchIn(source: java.lang.CharSequence): Option[Match] = { + def findFirstMatchIn(source: CharSequence): Option[Match] = { val m = pattern.matcher(source) if (m.find) Some(new Match(source, m, groupNames)) else None } @@ -262,7 +351,7 @@ class Regex(regex: String, groupNames: String*) extends Serializable { * @return A [[scala.Option]] of the matched prefix. * @example {{{"""[a-z]""".r findPrefixOf "A simple example." // returns None, since the text does not begin with a lowercase letter}}} */ - def findPrefixOf(source: java.lang.CharSequence): Option[String] = { + def findPrefixOf(source: CharSequence): Option[String] = { val m = pattern.matcher(source) if (m.lookingAt) Some(m.group) else None } @@ -279,7 +368,7 @@ class Regex(regex: String, groupNames: String*) extends Serializable { * @return A [[scala.Option]] of the [[scala.util.matching.Regex.Match]] of the matched string. * @example {{{"""\w+""".r findPrefixMatchOf "A simple example." map (_.after) // returns Some(" simple example.")}}} */ - def findPrefixMatchOf(source: java.lang.CharSequence): Option[Match] = { + def findPrefixMatchOf(source: CharSequence): Option[Match] = { val m = pattern.matcher(source) if (m.lookingAt) Some(new Match(source, m, groupNames)) else None } @@ -293,7 +382,7 @@ class Regex(regex: String, groupNames: String*) extends Serializable { * @return The resulting string * @example {{{"""\d+""".r replaceAllIn ("July 15", "<NUMBER>") // returns "July <NUMBER>"}}} */ - def replaceAllIn(target: java.lang.CharSequence, replacement: String): String = { + def replaceAllIn(target: CharSequence, replacement: String): String = { val m = pattern.matcher(target) m.replaceAll(replacement) } @@ -316,7 +405,7 @@ class Regex(regex: String, groupNames: String*) extends Serializable { * @param replacer The function which maps a match to another string. * @return The target string after replacements. */ - def replaceAllIn(target: java.lang.CharSequence, replacer: Match => String): String = { + def replaceAllIn(target: CharSequence, replacer: Match => String): String = { val it = new Regex.MatchIterator(target, this, groupNames).replacementData it foreach (md => it replace replacer(md)) it.replaced @@ -343,7 +432,7 @@ class Regex(regex: String, groupNames: String*) extends Serializable { * @param replacer The function which optionally maps a match to another string. * @return The target string after replacements. */ - def replaceSomeIn(target: java.lang.CharSequence, replacer: Match => Option[String]): String = { + def replaceSomeIn(target: CharSequence, replacer: Match => Option[String]): String = { val it = new Regex.MatchIterator(target, this, groupNames).replacementData for (matchdata <- it ; replacement <- replacer(matchdata)) it replace replacement @@ -359,7 +448,7 @@ class Regex(regex: String, groupNames: String*) extends Serializable { * @param replacement The string that will replace the match * @return The resulting string */ - def replaceFirstIn(target: java.lang.CharSequence, replacement: String): String = { + def replaceFirstIn(target: CharSequence, replacement: String): String = { val m = pattern.matcher(target) m.replaceFirst(replacement) } @@ -370,7 +459,7 @@ class Regex(regex: String, groupNames: String*) extends Serializable { * @return The array of strings computed by splitting the * input around matches of this regexp */ - def split(toSplit: java.lang.CharSequence): Array[String] = + def split(toSplit: CharSequence): Array[String] = pattern.split(toSplit) /** Create a new Regex with the same pattern, but no requirement that @@ -390,9 +479,11 @@ class Regex(regex: String, groupNames: String*) extends Serializable { * * @return The new unanchored regex */ - def unanchored: UnanchoredRegex = new Regex(regex, groupNames: _*) with UnanchoredRegex { override def anchored = outer } + def unanchored: UnanchoredRegex = new Regex(pattern, groupNames: _*) with UnanchoredRegex { override def anchored = outer } def anchored: Regex = this + def regex: String = pattern.pattern + /** The string defining the regular expression */ override def toString = regex } @@ -403,15 +494,7 @@ trait UnanchoredRegex extends Regex { } /** This object defines inner classes that describe - * regex matches and helper objects. The class hierarchy - * is as follows: - * - * {{{ - * MatchData - * / \ - * MatchIterator Match - * }}} - * + * regex matches and helper objects. */ object Regex { @@ -421,7 +504,7 @@ object Regex { trait MatchData { /** The source from where the match originated */ - val source: java.lang.CharSequence + val source: CharSequence /** The names of the groups, or some empty sequence if one defined */ val groupNames: Seq[String] @@ -459,25 +542,25 @@ object Regex { /** The char sequence before first character of match, * or `null` if nothing was matched */ - def before: java.lang.CharSequence = + def before: CharSequence = if (start >= 0) source.subSequence(0, start) else null /** The char sequence before first character of match in group `i`, * or `null` if nothing was matched for that group */ - def before(i: Int): java.lang.CharSequence = + def before(i: Int): CharSequence = if (start(i) >= 0) source.subSequence(0, start(i)) else null /** Returns char sequence after last character of match, * or `null` if nothing was matched */ - def after: java.lang.CharSequence = + def after: CharSequence = if (end >= 0) source.subSequence(end, source.length) else null /** The char sequence after last character of match in group `i`, * or `null` if nothing was matched for that group */ - def after(i: Int): java.lang.CharSequence = + def after(i: Int): CharSequence = if (end(i) >= 0) source.subSequence(end(i), source.length) else null @@ -501,8 +584,8 @@ object Regex { /** Provides information about a succesful match. */ - class Match(val source: java.lang.CharSequence, - matcher: Matcher, + class Match(val source: CharSequence, + private[matching] val matcher: Matcher, val groupNames: Seq[String]) extends MatchData { /** The index of the first matched character */ @@ -561,9 +644,17 @@ object Regex { def unapplySeq(m: Match): Option[Seq[String]] = if (m.groupCount > 0) Some(1 to m.groupCount map m.group) else None } - /** A class to step through a sequence of regex matches + /** A class to step through a sequence of regex matches. + * + * All methods inherited from [[scala.util.matching.Regex.MatchData]] will throw + * a [[java.lang.IllegalStateException]] until the matcher is initialized. The + * matcher can be initialized by calling `hasNext` or `next()` or causing these + * methods to be called, such as by invoking `toString` or iterating through + * the iterator's elements. + * + * @see [[java.util.regex.Matcher]] */ - class MatchIterator(val source: java.lang.CharSequence, val regex: Regex, val groupNames: Seq[String]) + class MatchIterator(val source: CharSequence, val regex: Regex, val groupNames: Seq[String]) extends AbstractIterator[String] with Iterator[String] with MatchData { self => protected[Regex] val matcher = regex.pattern.matcher(source) @@ -602,14 +693,14 @@ object Regex { /** Convert to an iterator that yields MatchData elements instead of Strings */ def matchData: Iterator[Match] = new AbstractIterator[Match] { def hasNext = self.hasNext - def next = { self.next; new Match(source, matcher, groupNames).force } + def next = { self.next(); new Match(source, matcher, groupNames).force } } /** Convert to an iterator that yields MatchData elements instead of Strings and has replacement support */ private[matching] def replacementData = new AbstractIterator[Match] with Replacement { def matcher = self.matcher def hasNext = self.hasNext - def next = { self.next; new Match(source, matcher, groupNames).force } + def next = { self.next(); new Match(source, matcher, groupNames).force } } } @@ -620,7 +711,7 @@ object Regex { private[matching] trait Replacement { protected def matcher: Matcher - private var sb = new java.lang.StringBuffer + private val sb = new java.lang.StringBuffer def replaced = { val newsb = new java.lang.StringBuffer(sb) @@ -631,6 +722,14 @@ object Regex { def replace(rs: String) = matcher.appendReplacement(sb, rs) } + /** Quotes strings to be used literally in regex patterns. + * + * All regex metacharacters in the input match themselves literally in the output. + * + * @example {{{List("US$", "CAN$").map(Regex.quote).mkString("|").r}}} + */ + def quote(text: String): String = Pattern quote text + /** Quotes replacement strings to be used in replacement methods. * * Replacement methods give special meaning to backslashes (`\`) and diff --git a/src/library/scala/util/parsing/ast/AbstractSyntax.scala b/src/library/scala/util/parsing/ast/AbstractSyntax.scala deleted file mode 100644 index 30b20d71c6..0000000000 --- a/src/library/scala/util/parsing/ast/AbstractSyntax.scala +++ /dev/null @@ -1,32 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2006-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala.util.parsing.ast - -import scala.util.parsing.input.Positional - -/** This component provides the core abstractions for representing an Abstract Syntax Tree - * - * @author Adriaan Moors - */ -@deprecated("This class will be removed", "2.10.0") -trait AbstractSyntax { - /** The base class for elements of the abstract syntax tree. - */ - trait Element extends Positional - - /** The base class for elements in the AST that represent names [[scala.util.parsing.ast.Binders]]. - */ - trait NameElement extends Element { - def name: String - override def equals(that: Any): Boolean = that match { - case n: NameElement => n.name == name - case _ => false - } - } -} diff --git a/src/library/scala/util/parsing/ast/Binders.scala b/src/library/scala/util/parsing/ast/Binders.scala deleted file mode 100644 index a6ad1907c2..0000000000 --- a/src/library/scala/util/parsing/ast/Binders.scala +++ /dev/null @@ -1,347 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2006-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala.util.parsing.ast - -import scala.collection.AbstractIterable -import scala.collection.mutable -import scala.language.implicitConversions - -//DISCLAIMER: this code is highly experimental! - - // TODO: avoid clashes when substituting - // TODO: check binders in the same scope are distinct - -/** This trait provides the core ''Scrap-Your-Boilerplate'' abstractions as - * well as implementations for common datatypes. - * - * (Based on Ralf Lämmel's [[http://homepages.cwi.nl/~ralf/syb3/ SYB papers]].) - * - * @author Adriaan Moors - */ -@deprecated("This class will be removed", "2.10.0") -trait Mappable { - trait Mapper { def apply[T <% Mappable[T]](x: T): T } /* TODO: having type `Forall T. T => T` is too strict: - sometimes we want to allow `Forall T >: precision. T => T` for some type `precision`, so that, - beneath a certain threshold, we have some leeway. - concretely: to use gmap for substitution, we simply require that ast nodes are mapped to ast nodes, - we can't require that the type is preserved precisely: a Name may map to e.g., a MethodCall - */ - - trait Mappable[T] { - // one-layer traversal - def gmap(f: Mapper): T - // everywhere f x = f (gmapT (everywhere f) x) - def everywhere(f: Mapper)(implicit c: T => Mappable[T]): T = - f(gmap(new Mapper { def apply[T <% Mappable[T]](x: T): T = x.everywhere(f)})) - } - - implicit def StringIsMappable(s: String): Mappable[String] = - new Mappable[String] { - def gmap(f: Mapper): String = f(s) - } - - implicit def ListIsMappable[t <% Mappable[t]](xs: List[t]): Mappable[List[t]] = - new Mappable[List[t]] { - def gmap(f: Mapper): List[t] = (for (x <- xs) yield f(x)).toList - } - - implicit def OptionIsMappable[t <% Mappable[t]](xs: Option[t]): Mappable[Option[t]] = - new Mappable[Option[t]] { - def gmap(f: Mapper): Option[t] = (for (x <- xs) yield f(x)) - } -} - -/** This component provides functionality for enforcing variable binding - * during parse-time. - * - * When parsing simple languages, like Featherweight Scala, these parser - * combinators will fully enforce the binding discipline. When names are - * allowed to be left unqualified, these mechanisms would have to be - * complemented by an extra phase that resolves names that couldn't be - * resolved using the naive binding rules. (Maybe some machinery to - * model `implicit` binders (e.g., `this` and imported qualifiers) - * and selection on a binder will suffice?) - * - * @author Adriaan Moors - */ -trait Binders extends AbstractSyntax with Mappable { - /** A `Scope` keeps track of one or more syntactic elements that represent bound names. - * The elements it contains share the same scope and must all be distinct, as determined by `==`. - * - * A `NameElement` `n` in the AST that is conceptually bound by a `Scope` `s`, is replaced by a - * `BoundElement(n, s)`. (For example, in `val x:Int=x+1`, the first `x` is modelled by a - * Scope `s` that contains `x` and the second `x` is represented by a `BoundElement(x, s)`) - * The term (`x+1`) in scope of the Scope becomes an `UnderBinder(s, x+1)`. - * - * A `NameElement` `n` is bound by a `Scope` `s` if it is wrapped as a `BoundElement(n, s)`, and - * `s` has a binder element that is semantically equal (`equals` or `==`) to `n`. - * - * A `Scope` is represented textually by its list of binder elements, followed by the scope's `id`. - * For example: `[x, y]!1` represents the scope with `id` `1` and binder elements `x` and `y`. - * (`id` is solely used for this textual representation.) - */ - class Scope[binderType <: NameElement] extends AbstractIterable[binderType] with Iterable[binderType] { - private val substitution: mutable.Map[binderType, Element] = - new mutable.LinkedHashMap[binderType, Element] // a LinkedHashMap is ordered by insertion order -- important! - - /** Returns a unique number identifying this Scope (only used for representation purposes). */ - val id: Int = _Binder.genId - - /** Returns the binders in this scope. - * For a typical let-binding, this is just the variable name. For an argument list to a method body, - * there is one binder per formal argument. - */ - def iterator = substitution.keysIterator - - /** Return the `i`th binder in this scope. */ - def apply(i: Int): binderType = this.iterator.toList(i) - - /** Returns true if this container has a binder equal (as determined by `==`) to `b`. */ - def binds(b: binderType): Boolean = substitution.contains(b) - - def indexFor(b: binderType): Option[Int] = { - val iter = this.iterator.zipWithIndex - for ((that, count) <- iter) { - if (that.name == b.name) // TODO: why do name equals and structural equals differ? - return Some(count + 1) - else - Console.println(that+"!="+b) - } - - None - } - - /** Adds a new binder, for example the variable name in a local variable declaration. - * - * @param b a new binder that is distinct from the existing binders in this scope, - * and shares their conceptual scope. `canAddBinder(b)` must hold. - * @return `binds(b)` and `getElementFor(b) eq b` will hold. - */ - def addBinder(b: binderType) { substitution += Pair(b, b) } - - // TODO: strengthen this condition so that no binders may be added after this scope has been - // linked to its `UnderBinder` (i.e., while parsing, BoundElements may be added to the Scope - // associated to the UnderBinder, but after that, no changes are allowed, except for substitution)? - /** `canAddElement` indicates whether `b` may be added to this scope. - * - * - * @return true if `b` had not been added yet - */ - def canAddBinder(b: binderType): Boolean = !binds(b) - - /** ''Replaces'' the bound occurrences of a contained binder by their new value. - * The bound occurrences of `b` are not actually replaced; the scope keeps track - * of a substitution that maps every binder to its current value. Since a `BoundElement` is - * a proxy for the element it is bound to by its binder, `substitute` may thus be thought of - * as replacing all the bound occurrences of the given binder `b` by their new value `value`. - * - * @param b the binder whose bound occurrences should be given a new value. `binds(b)` must hold. - * @param value the new value for the bound occurrences of `b` - * @return `getElementFor(b) eq value` will hold. - */ - def substitute(b: binderType, value: Element): Unit = substitution(b) = value - - /** Returns the current value for the bound occurrences of `b`. - * - * @param b the contained binder whose current value should be returned `binds(b)` must hold. - */ - def getElementFor(b: binderType): Element = substitution(b) - - override def toString: String = this.iterator.toList.mkString("[",", ","]")+"!"+id // TODO show substitution? - - /** Returns a list of strings that represent the binder elements, each tagged with this scope's id. */ - def bindersToString: List[String] = (for(b <- this.iterator) yield b+"!"+id).toList - - /** Return a new inheriting scope that won't check whether binding is respected until the scope is left (so as to support forward references). */ - def allowForwardRef: Scope[binderType] = this // TODO - - /** Return a nested scope -- binders entered into it won't be visible in this scope, but if this scope allows forward references, - * the binding in the returned scope also does, and thus the check that all variables are bound is deferred until this scope is left. - */ - def nested: Scope[binderType] = this // TODO - - def onEnter() {} - def onLeft() {} - } - - - trait BindingSensitive { - // would like to specify this as one method: - // def alpha_==[t <: NameElement](other: BoundElement[t]): Boolean - // def alpha_==[bt <: binderType, st <: elementT](other: UnderBinder[bt, st]): Boolean - } - - /** A `BoundElement` is bound in a certain scope `scope`, which keeps track of the actual element that - * `el` stands for. - * - * A `BoundElement` is represented textually by its bound element, followed by its scope's `id`. - * For example: `x@1` represents the variable `x` that is bound in the scope with `id` `1`. - * - * @note `scope.binds(el)` holds before and after. - */ - case class BoundElement[boundElement <: NameElement](el: boundElement, scope: Scope[boundElement]) extends NameElement with Proxy with BindingSensitive { - /** Returns the element this `BoundElement` stands for. - * The `Proxy` trait ensures `equals`, `hashCode` and `toString` are forwarded to - * the result of this method. - */ - def self: Element = scope.getElementFor(el) - - def name = self.asInstanceOf[NameElement].name // TODO: this is only safe when substituted to a NameElement, which certainly isn't required -- I want dynamic inheritance! :) - - // decorate element's representation with the id of the scope it's bound in - override def toString: String = super.toString+"@"+scope.id - - def alpha_==[t <: NameElement](other: BoundElement[t]): Boolean = scope.indexFor(el) == other.scope.indexFor(other.el) - } - - /** A variable that escaped its scope (i.e., a free variable) -- we don't deal very well with these yet. */ - class UnboundElement[N <: NameElement](private val el: N) extends NameElement { - def name = el.name+"@??" - } - - // this is useless, as Element is a supertype of BoundElement --> the coercion will never be inferred - // if we knew a more specific type for the element that the bound element represents, this could make sense - // implicit def BoundElementProxy[t <: NameElement](e: BoundElement[t]): Element = e.self - - /** Represents an element with variables that are bound in a certain scope. */ - class UnderBinder[binderType <: NameElement, elementT <% Mappable[elementT]](val scope: Scope[binderType], private[Binders] val element: elementT) extends Element with BindingSensitive { - override def toString: String = "(" + scope.toString + ") in { "+element.toString+" }" - - /** Alpha-equivalence -- TODO - * Returns true if the `element` of the `other` `UnderBinder` is equal to this `element` up to alpha-conversion. - * - * That is, regular equality is used for all elements but `BoundElement`s: such an element is - * equal to a `BoundElement` in `other` if their binders are equal. Binders are equal if they - * are at the same index in their respective scope. - * - * Example: - * {{{ - * UnderBinder([x, y]!1, x@1) alpha_== UnderBinder([a, b]!2, a@2) - * ! (UnderBinder([x, y]!1, y@1) alpha_== UnderBinder([a, b]!2, a@2)) - * }}} - */ - /*def alpha_==[bt <: binderType, st <: elementT](other: UnderBinder[bt, st]): Boolean = { - var result = true - - // TODO: generic zip or gmap2 - element.gmap2(other.element, new Mapper2 { - def apply[s <% Mappable[s], t <% Mappable[t]](x :{s, t}): {s, t} = x match { - case {be1: BoundElement[_], be2: BoundElement[_]} => result == result && be1.alpha_==(be2) // monadic gmap (cheating using state directly) - case {ub1: UnderBinder[_, _], ub2: UnderBinder[_, _]} => result == result && be1.alpha_==(be2) - case {a, b} => result == result && a.equals(b) - }; x - }) - }*/ - - def cloneElementWithSubst(subst: Map[NameElement, NameElement]) = element.gmap(new Mapper { def apply[t <% Mappable[t]](x :t): t = x match{ - case substable: NameElement if subst.contains(substable) => subst.get(substable).asInstanceOf[t] // TODO: wrong... substitution is not (necessarily) the identity function - //Console.println("substed: "+substable+"-> "+subst.get(substable)+")"); - case x => x // Console.println("subst: "+x+"(keys: "+subst.keys+")");x - }}) - - // TODO - def cloneElementNoBoundElements = element.gmap(new Mapper { def apply[t <% Mappable[t]](x :t): t = x match{ - case BoundElement(el, _) => new UnboundElement(el).asInstanceOf[t] // TODO: precision stuff - case x => x - }}) - - def extract: elementT = cloneElementNoBoundElements - def extract(subst: Map[NameElement, NameElement]): elementT = cloneElementWithSubst(subst) - - /** Get a string representation of element, normally we don't allow direct access to element, but just getting a string representation is ok. */ - def elementToString: String = element.toString - } - - //SYB type class instances - implicit def UnderBinderIsMappable[bt <: NameElement <% Mappable[bt], st <% Mappable[st]](ub: UnderBinder[bt, st]): Mappable[UnderBinder[bt, st]] = - new Mappable[UnderBinder[bt, st]] { - def gmap(f: Mapper): UnderBinder[bt, st] = UnderBinder(f(ub.scope), f(ub.element)) - } - - implicit def ScopeIsMappable[bt <: NameElement <% Mappable[bt]](scope: Scope[bt]): Mappable[Scope[bt]] = - new Mappable[Scope[bt]] { - def gmap(f: Mapper): Scope[bt] = { val newScope = new Scope[bt]() - for(b <- scope) newScope.addBinder(f(b)) - newScope - } - } - - implicit def NameElementIsMappable(self: NameElement): Mappable[NameElement] = new Mappable[NameElement] { - def gmap(f: Mapper): NameElement = self match { - case BoundElement(el, scope) => BoundElement(f(el), f(scope)) - case _ => UserNameElementIsMappable(self).gmap(f) - } - } - - def UserNameElementIsMappable[t <: NameElement](self: t): Mappable[t] - - object UnderBinder { - def apply[binderType <: NameElement, elementT <% Mappable[elementT]](scope: Scope[binderType], element: elementT) = new UnderBinder(scope, element) - def unit[bt <: NameElement, elementT <% Mappable[elementT]](x: elementT) = UnderBinder(new Scope[bt](), x) - } - - /** If a list of `UnderBinder`s all have the same scope, they can be turned in to an `UnderBinder` - * containing a list of the elements in the original `UnderBinder`. - * - * The name `sequence` comes from the fact that this method's type is equal to the type of monadic sequence. - * - * @note `!orig.isEmpty` implies `orig.forall(ub => ub.scope eq orig(0).scope)` - * - */ - def sequence[bt <: NameElement, st <% Mappable[st]](orig: List[UnderBinder[bt, st]]): UnderBinder[bt, List[st]] = - if(orig.isEmpty) UnderBinder.unit(Nil) - else UnderBinder(orig(0).scope, orig.map(_.element)) - - // couldn't come up with a better name... - def unsequence[bt <: NameElement, st <% Mappable[st]](orig: UnderBinder[bt, List[st]]): List[UnderBinder[bt, st]] = - orig.element.map(sc => UnderBinder(orig.scope, sc)) - - //TODO: more documentation - /** An environment that maps a `NameElement` to the scope in which it is bound. - * This can be used to model scoping during parsing. - * - * @note This class uses similar techniques as described by ''Burak Emir'' in - * [[http://library.epfl.ch/theses/?nr=3899 Object-oriented pattern matching]], - * but uses `==` instead of `eq`, thus types can't be unified in general. - */ - abstract class BinderEnv { - def apply[A <: NameElement](v: A): Option[Scope[A]] - def extend[a <: NameElement](v : a, x : Scope[a]) = new BinderEnv { - def apply[b <: NameElement](w : b): Option[Scope[b]] = - if(w == v) Some(x.asInstanceOf[Scope[b]]) - else BinderEnv.this.apply(w) - } - } - - object EmptyBinderEnv extends BinderEnv { - def apply[A <: NameElement](v: A): Option[Scope[A]] = None - } - - // TODO: move this to some utility object higher in the scala hierarchy? - /** Returns a given result, but executes the supplied closure before returning. - * (The effect of this closure does not influence the returned value.) - */ - trait ReturnAndDo[T]{ - /** - * @param block code to be executed, purely for its side-effects - */ - def andDo(block: => Unit): T - } - - def return_[T](result: T): ReturnAndDo[T] = - new ReturnAndDo[T] { - val r = result - def andDo(block: => Unit): T = {block; r} - } - - private object _Binder { - private var currentId = 0 - private[Binders] def genId = return_(currentId) andDo {currentId=currentId+1} - } -} diff --git a/src/library/scala/util/parsing/combinator/ImplicitConversions.scala b/src/library/scala/util/parsing/combinator/ImplicitConversions.scala deleted file mode 100644 index ad06749c0d..0000000000 --- a/src/library/scala/util/parsing/combinator/ImplicitConversions.scala +++ /dev/null @@ -1,42 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2006-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - -package scala.util.parsing.combinator - -import scala.language.implicitConversions - -/** This object contains implicit conversions that come in handy when using the `^^` combinator. - * - * Refer to [[scala.util.parsing.combinator.Parsers]] to construct an AST from the concrete syntax. - * - * The reason for this is that the sequential composition combinator (`~`) combines its constituents - * into a ~. When several `~`s are combined, this results in nested `~`s (to the left). - * The `flatten*` coercions makes it easy to apply an `n`-argument function to a nested `~` of - * depth `n-1` - * - * The `headOptionTailToFunList` converts a function that takes a `List[A]` to a function that - * accepts a `~[A, Option[List[A]]]` (this happens when parsing something of the following - * shape: `p ~ opt("." ~ repsep(p, "."))` -- where `p` is a parser that yields an `A`). - * - * @author Martin Odersky - * @author Iulian Dragos - * @author Adriaan Moors - */ -trait ImplicitConversions { self: Parsers => - implicit def flatten2[A, B, C] (f: (A, B) => C) = - (p: ~[A, B]) => p match {case a ~ b => f(a, b)} - implicit def flatten3[A, B, C, D] (f: (A, B, C) => D) = - (p: ~[~[A, B], C]) => p match {case a ~ b ~ c => f(a, b, c)} - implicit def flatten4[A, B, C, D, E] (f: (A, B, C, D) => E) = - (p: ~[~[~[A, B], C], D]) => p match {case a ~ b ~ c ~ d => f(a, b, c, d)} - implicit def flatten5[A, B, C, D, E, F](f: (A, B, C, D, E) => F) = - (p: ~[~[~[~[A, B], C], D], E]) => p match {case a ~ b ~ c ~ d ~ e=> f(a, b, c, d, e)} - implicit def headOptionTailToFunList[A, T] (f: List[A] => T)= - (p: ~[A, Option[List[A]]]) => f(p._1 :: (p._2 match { case Some(xs) => xs case None => Nil})) -} diff --git a/src/library/scala/util/parsing/combinator/JavaTokenParsers.scala b/src/library/scala/util/parsing/combinator/JavaTokenParsers.scala deleted file mode 100644 index 89832d3fb2..0000000000 --- a/src/library/scala/util/parsing/combinator/JavaTokenParsers.scala +++ /dev/null @@ -1,61 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2006-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - -package scala.util.parsing.combinator - -import scala.annotation.migration - -/** `JavaTokenParsers` differs from [[scala.util.parsing.combinator.RegexParsers]] - * by adding the following definitions: - * - * - `ident` - * - `wholeNumber` - * - `decimalNumber` - * - `stringLiteral` - * - `floatingPointNumber` - */ -trait JavaTokenParsers extends RegexParsers { - /** Anything that is a valid Java identifier, according to - * <a href="http://docs.oracle.com/javase/specs/jls/se7/html/jls-3.html#jls-3.8">The Java Language Spec</a>. - * Generally, this means a letter, followed by zero or more letters or numbers. - */ - def ident: Parser[String] = - """\p{javaJavaIdentifierStart}\p{javaJavaIdentifierPart}*""".r - /** An integer, without sign or with a negative sign. */ - def wholeNumber: Parser[String] = - """-?\d+""".r - /** Number following one of these rules: - * - * - An integer. For example: `13` - * - An integer followed by a decimal point. For example: `3.` - * - An integer followed by a decimal point and fractional part. For example: `3.14` - * - A decimal point followed by a fractional part. For example: `.1` - */ - def decimalNumber: Parser[String] = - """(\d+(\.\d*)?|\d*\.\d+)""".r - /** Double quotes (`"`) enclosing a sequence of: - * - * - Any character except double quotes, control characters or backslash (`\`) - * - A backslash followed by another backslash, a single or double quote, or one - * of the letters `b`, `f`, `n`, `r` or `t` - * - `\` followed by `u` followed by four hexadecimal digits - */ - @migration("`stringLiteral` allows escaping single and double quotes, but not forward slashes any longer.", "2.10.0") - def stringLiteral: Parser[String] = - ("\""+"""([^"\p{Cntrl}\\]|\\[\\'"bfnrt]|\\u[a-fA-F0-9]{4})*"""+"\"").r - /** A number following the rules of `decimalNumber`, with the following - * optional additions: - * - * - Preceded by a negative sign - * - Followed by `e` or `E` and an optionally signed integer - * - Followed by `f`, `f`, `d` or `D` (after the above rule, if both are used) - */ - def floatingPointNumber: Parser[String] = - """-?(\d+(\.\d*)?|\d*\.\d+)([eE][+-]?\d+)?[fFdD]?""".r -} diff --git a/src/library/scala/util/parsing/combinator/PackratParsers.scala b/src/library/scala/util/parsing/combinator/PackratParsers.scala deleted file mode 100644 index 16705d45f9..0000000000 --- a/src/library/scala/util/parsing/combinator/PackratParsers.scala +++ /dev/null @@ -1,312 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2006-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala.util.parsing.combinator - -import scala.util.parsing.combinator._ -import scala.util.parsing.input.{ Reader, Position } -import scala.collection.mutable -import scala.language.implicitConversions - -/** - * `PackratParsers` is a component that extends the parser combinators - * provided by [[scala.util.parsing.combinator.Parsers]] with a memoization - * facility (''Packrat Parsing''). - * - * Packrat Parsing is a technique for implementing backtracking, - * recursive-descent parsers, with the advantage that it guarantees - * unlimited lookahead and a linear parse time. Using this technique, - * left recursive grammars can also be accepted. - * - * Using `PackratParsers` is very similar to using `Parsers`: - * - any class/trait that extends `Parsers` (directly or through a subclass) - * can mix in `PackratParsers`. - * Example: `'''object''' MyGrammar '''extends''' StandardTokenParsers '''with''' PackratParsers` - * - each grammar production previously declared as a `def` without formal - * parameters becomes a `lazy val`, and its type is changed from - * `Parser[Elem]` to `PackratParser[Elem]`. - * So, for example, `'''def''' production: Parser[Int] = {...}` - * becomes `'''lazy val''' production: PackratParser[Int] = {...}` - * - Important: using `PackratParser`s is not an ''all or nothing'' decision. - * They can be free mixed with regular `Parser`s in a single grammar. - * - * Cached parse results are attached to the ''input'', not the grammar. - * Therefore, `PackratsParser`s require a `PackratReader` as input, which - * adds memoization to an underlying `Reader`. Programmers can create - * `PackratReader` objects either manually, as in - * `production('''new''' PackratReader('''new''' lexical.Scanner("input")))`, - * but the common way should be to rely on the combinator `phrase` to wrap - * a given input with a `PackratReader` if the input is not one itself. - * - * @see Bryan Ford: "Packrat Parsing: Simple, Powerful, Lazy, Linear Time." ICFP'02 - * @see Alessandro Warth, James R. Douglass, Todd Millstein: "Packrat Parsers Can Support Left Recursion." PEPM'08 - * - * @since 2.8 - * @author Manohar Jonnalagedda - * @author Tiark Rompf - */ - -trait PackratParsers extends Parsers { - - //type Input = PackratReader[Elem] - - /** - * A specialized `Reader` class that wraps an underlying `Reader` - * and provides memoization of parse results. - */ - class PackratReader[+T](underlying: Reader[T]) extends Reader[T] { outer => - - /* - * caching of intermediate parse results and information about recursion - */ - private[PackratParsers] val cache = mutable.HashMap.empty[(Parser[_], Position), MemoEntry[_]] - - private[PackratParsers] def getFromCache[T](p: Parser[T]): Option[MemoEntry[T]] = { - cache.get((p, pos)).asInstanceOf[Option[MemoEntry[T]]] - } - - private[PackratParsers] def updateCacheAndGet[T](p: Parser[T], w: MemoEntry[T]): MemoEntry[T] = { - cache.put((p, pos),w) - w - } - - /* a cache for storing parser heads: allows to know which parser is involved - in a recursion*/ - private[PackratParsers] val recursionHeads: mutable.HashMap[Position, Head] = mutable.HashMap.empty - - //a stack that keeps a list of all involved rules - private[PackratParsers] var lrStack: List[LR] = Nil - - override def source: java.lang.CharSequence = underlying.source - override def offset: Int = underlying.offset - - def first: T = underlying.first - def rest: Reader[T] = new PackratReader(underlying.rest) { - override private[PackratParsers] val cache = outer.cache - override private[PackratParsers] val recursionHeads = outer.recursionHeads - lrStack = outer.lrStack - } - - def pos: Position = underlying.pos - def atEnd: Boolean = underlying.atEnd - } - - /** - * A parser generator delimiting whole phrases (i.e. programs). - * - * Overridden to make sure any input passed to the argument parser - * is wrapped in a `PackratReader`. - */ - override def phrase[T](p: Parser[T]) = { - val q = super.phrase(p) - new PackratParser[T] { - def apply(in: Input) = in match { - case in: PackratReader[_] => q(in) - case in => q(new PackratReader(in)) - } - } - } - - private def getPosFromResult(r: ParseResult[_]): Position = r.next.pos - - // auxiliary data structures - - private case class MemoEntry[+T](var r: Either[LR,ParseResult[_]]){ - def getResult: ParseResult[T] = r match { - case Left(LR(res,_,_)) => res.asInstanceOf[ParseResult[T]] - case Right(res) => res.asInstanceOf[ParseResult[T]] - } - } - - private case class LR(var seed: ParseResult[_], var rule: Parser[_], var head: Option[Head]){ - def getPos: Position = getPosFromResult(seed) - } - - private case class Head(var headParser: Parser[_], var involvedSet: List[Parser[_]], var evalSet: List[Parser[_]]){ - def getHead = headParser - } - - /** - * The root class of packrat parsers. - */ - abstract class PackratParser[+T] extends super.Parser[T] - - /** - * Implicitly convert a parser to a packrat parser. - * The conversion is triggered by giving the appropriate target type: - * {{{ - * val myParser: PackratParser[MyResult] = aParser - * }}} */ - implicit def parser2packrat[T](p: => super.Parser[T]): PackratParser[T] = { - lazy val q = p - memo(super.Parser {in => q(in)}) - } - - /* - * An unspecified function that is called when a packrat reader is applied. - * It verifies whether we are in the process of growing a parse or not. - * In the former case, it makes sure that rules involved in the recursion are evaluated. - * It also prevents non-involved rules from getting evaluated further - */ - private def recall(p: super.Parser[_], in: PackratReader[Elem]): Option[MemoEntry[_]] = { - val cached = in.getFromCache(p) - val head = in.recursionHeads.get(in.pos) - - head match { - case None => /*no heads*/ cached - case Some(h@Head(hp, involved, evalSet)) => { - //heads found - if(cached == None && !(hp::involved contains p)) { - //Nothing in the cache, and p is not involved - return Some(MemoEntry(Right(Failure("dummy ",in)))) - } - if(evalSet contains p){ - //something in cache, and p is in the evalSet - //remove the rule from the evalSet of the Head - h.evalSet = h.evalSet.filterNot(_==p) - val tempRes = p(in) - //we know that cached has an entry here - val tempEntry: MemoEntry[_] = cached.get // match {case Some(x: MemoEntry[_]) => x} - //cache is modified - tempEntry.r = Right(tempRes) - } - cached - } - } - } - - /* - * setting up the left-recursion. We have the LR for the rule head - * we modify the involvedSets of all LRs in the stack, till we see - * the current parser again - */ - private def setupLR(p: Parser[_], in: PackratReader[_], recDetect: LR): Unit = { - if(recDetect.head == None) recDetect.head = Some(Head(p, Nil, Nil)) - - in.lrStack.takeWhile(_.rule != p).foreach {x => - x.head = recDetect.head - recDetect.head.map(h => h.involvedSet = x.rule::h.involvedSet) - } - } - - /* - * growing, if needed the recursion - * check whether the parser we are growing is the head of the rule. - * Not => no grow - */ - - /* - * Once the result of the recall function is known, if it is nil, then we need to store a dummy -failure into the cache (much like in the previous listings) and compute the future parse. If it -is not, however, this means we have detected a recursion, and we use the setupLR function -to update each parser involved in the recursion. - */ - - private def lrAnswer[T](p: Parser[T], in: PackratReader[Elem], growable: LR): ParseResult[T] = growable match { - //growable will always be having a head, we can't enter lrAnswer otherwise - case LR(seed ,rule, Some(head)) => - if(head.getHead != p) /*not head rule, so not growing*/ seed.asInstanceOf[ParseResult[T]] - else { - in.updateCacheAndGet(p, MemoEntry(Right[LR, ParseResult[T]](seed.asInstanceOf[ParseResult[T]]))) - seed match { - case f@Failure(_,_) => f - case e@Error(_,_) => e - case s@Success(_,_) => /*growing*/ grow(p, in, head) - } - } - case _=> throw new Exception("lrAnswer with no head !!") - } - - //p here should be strict (cannot be non-strict) !! - //failing left-recursive grammars: This is done by simply storing a failure if nothing is found - - /** - * Explicitly convert a given parser to a memoizing packrat parser. - * In most cases, client code should avoid calling `memo` directly - * and rely on implicit conversion instead. - */ - def memo[T](p: super.Parser[T]): PackratParser[T] = { - new PackratParser[T] { - def apply(in: Input) = { - /* - * transformed reader - */ - val inMem = in.asInstanceOf[PackratReader[Elem]] - - //look in the global cache if in a recursion - val m = recall(p, inMem) - m match { - //nothing has been done due to recall - case None => - val base = LR(Failure("Base Failure",in), p, None) - inMem.lrStack = base::inMem.lrStack - //cache base result - inMem.updateCacheAndGet(p,MemoEntry(Left(base))) - //parse the input - val tempRes = p(in) - //the base variable has passed equality tests with the cache - inMem.lrStack = inMem.lrStack.tail - //check whether base has changed, if yes, we will have a head - base.head match { - case None => - /*simple result*/ - inMem.updateCacheAndGet(p,MemoEntry(Right(tempRes))) - tempRes - case s@Some(_) => - /*non simple result*/ - base.seed = tempRes - //the base variable has passed equality tests with the cache - val res = lrAnswer(p, inMem, base) - res - } - - case Some(mEntry) => { - //entry found in cache - mEntry match { - case MemoEntry(Left(recDetect)) => { - setupLR(p, inMem, recDetect) - //all setupLR does is change the heads of the recursions, so the seed will stay the same - recDetect match {case LR(seed, _, _) => seed.asInstanceOf[ParseResult[T]]} - } - case MemoEntry(Right(res: ParseResult[_])) => res.asInstanceOf[ParseResult[T]] - } - } - } - } - } - } - - private def grow[T](p: super.Parser[T], rest: PackratReader[Elem], head: Head): ParseResult[T] = { - //store the head into the recursionHeads - rest.recursionHeads.put(rest.pos, head /*match {case Head(hp,involved,_) => Head(hp,involved,involved)}*/) - val oldRes: ParseResult[T] = rest.getFromCache(p).get match { - case MemoEntry(Right(x)) => x.asInstanceOf[ParseResult[T]] - case _ => throw new Exception("impossible match") - } - - //resetting the evalSet of the head of the recursion at each beginning of growth - head.evalSet = head.involvedSet - val tempRes = p(rest); tempRes match { - case s@Success(_,_) => - if(getPosFromResult(oldRes) < getPosFromResult(tempRes)) { - rest.updateCacheAndGet(p, MemoEntry(Right(s))) - grow(p, rest, head) - } else { - //we're done with growing, we can remove data from recursion head - rest.recursionHeads -= rest.pos - rest.getFromCache(p).get match { - case MemoEntry(Right(x: ParseResult[_])) => x.asInstanceOf[ParseResult[T]] - case _ => throw new Exception("impossible match") - } - } - case f => - rest.recursionHeads -= rest.pos - /*rest.updateCacheAndGet(p, MemoEntry(Right(f)));*/oldRes - } - } -} diff --git a/src/library/scala/util/parsing/combinator/Parsers.scala b/src/library/scala/util/parsing/combinator/Parsers.scala deleted file mode 100644 index ead444653e..0000000000 --- a/src/library/scala/util/parsing/combinator/Parsers.scala +++ /dev/null @@ -1,928 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2006-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala.util.parsing.combinator - -import scala.util.parsing.input._ -import scala.collection.mutable.ListBuffer -import scala.annotation.tailrec -import scala.annotation.migration -import scala.language.implicitConversions -import scala.util.DynamicVariable - -// TODO: better error handling (labelling like parsec's <?>) - -/** `Parsers` is a component that ''provides'' generic parser combinators. - * - * There are two abstract members that must be defined in order to - * produce parsers: the type `Elem` and - * [[scala.util.parsing.combinator.Parsers.Parser]]. There are helper - * methods that produce concrete `Parser` implementations -- see ''primitive - * parser'' below. - * - * A `Parsers` may define multiple `Parser` instances, which are combined - * to produced the desired parser. - * - * The type of the elements these parsers should parse must be defined - * by declaring `Elem` - * (each parser is polymorphic in the type of result it produces). - * - * There are two aspects to the result of a parser: - * 1. success or failure - * 1. the result. - * - * A [[scala.util.parsing.combinator.Parsers.Parser]] produces both kinds of information, - * by returning a [[scala.util.parsing.combinator.Parsers.ParseResult]] when its `apply` - * method is called on an input. - * - * The term ''parser combinator'' refers to the fact that these parsers - * are constructed from primitive parsers and composition operators, such - * as sequencing, alternation, optionality, repetition, lifting, and so on. For example, - * given `p1` and `p2` of type [[scala.util.parsing.combinator.Parsers.Parser]]: - * - * {{{ - * p1 ~ p2 // sequencing: must match p1 followed by p2 - * p1 | p2 // alternation: must match either p1 or p2, with preference given to p1 - * p1.? // optionality: may match p1 or not - * p1.* // repetition: matches any number of repetitions of p1 - * }}} - * - * These combinators are provided as methods on [[scala.util.parsing.combinator.Parsers.Parser]], - * or as methods taking one or more `Parsers` and returning a `Parser` provided in - * this class. - * - * A ''primitive parser'' is a parser that accepts or rejects a single - * piece of input, based on a certain criterion, such as whether the - * input... - * - is equal to some given object (see method `accept`), - * - satisfies a certain predicate (see method `acceptIf`), - * - is in the domain of a given partial function (see method `acceptMatch`) - * - or other conditions, by using one of the other methods available, or subclassing `Parser` - * - * Even more primitive parsers always produce the same result, irrespective of the input. See - * methods `success`, `err` and `failure` as examples. - * - * @see [[scala.util.parsing.combinator.RegexParsers]] and other known subclasses for practical examples. - * - * @author Martin Odersky - * @author Iulian Dragos - * @author Adriaan Moors - */ -trait Parsers { - /** the type of input elements the provided parsers consume (When consuming - * invidual characters, a parser is typically called a ''scanner'', which - * produces ''tokens'' that are consumed by what is normally called a ''parser''. - * Nonetheless, the same principles apply, regardless of the input type.) */ - type Elem - - /** The parser input is an abstract reader of input elements, i.e. the type - * of input the parsers in this component expect. */ - type Input = Reader[Elem] - - /** A base class for parser results. A result is either successful or not - * (failure may be fatal, i.e., an Error, or not, i.e., a Failure). On - * success, provides a result of type `T` which consists of some result - * (and the rest of the input). */ - sealed abstract class ParseResult[+T] { - /** Functional composition of ParseResults. - * - * @param f the function to be lifted over this result - * @return `f` applied to the result of this `ParseResult`, packaged up as a new `ParseResult` - */ - def map[U](f: T => U): ParseResult[U] - - /** Partial functional composition of ParseResults. - * - * @param f the partial function to be lifted over this result - * @param error a function that takes the same argument as `f` and - * produces an error message to explain why `f` wasn't applicable - * (it is called when this is the case) - * @return if `f` f is defined at the result in this `ParseResult`, `f` - * applied to the result of this `ParseResult`, packaged up as - * a new `ParseResult`. If `f` is not defined, `Failure`. - */ - def mapPartial[U](f: PartialFunction[T, U], error: T => String): ParseResult[U] - - def flatMapWithNext[U](f: T => Input => ParseResult[U]): ParseResult[U] - - def filterWithError(p: T => Boolean, error: T => String, position: Input): ParseResult[T] - - def append[U >: T](a: => ParseResult[U]): ParseResult[U] - - def isEmpty = !successful - - /** Returns the embedded result. */ - def get: T - - def getOrElse[B >: T](default: => B): B = - if (isEmpty) default else this.get - - val next: Input - - val successful: Boolean - } - - /** The success case of `ParseResult`: contains the result and the remaining input. - * - * @param result The parser's output - * @param next The parser's remaining input - */ - case class Success[+T](result: T, override val next: Input) extends ParseResult[T] { - def map[U](f: T => U) = Success(f(result), next) - def mapPartial[U](f: PartialFunction[T, U], error: T => String): ParseResult[U] - = if(f.isDefinedAt(result)) Success(f(result), next) - else Failure(error(result), next) - - def flatMapWithNext[U](f: T => Input => ParseResult[U]): ParseResult[U] - = f(result)(next) - - def filterWithError(p: T => Boolean, error: T => String, position: Input): ParseResult[T] = - if (p(result)) this - else Failure(error(result), position) - - def append[U >: T](a: => ParseResult[U]): ParseResult[U] = this - - def get: T = result - - /** The toString method of a Success. */ - override def toString = "["+next.pos+"] parsed: "+result - - val successful = true - } - - private lazy val lastNoSuccessVar = new DynamicVariable[Option[NoSuccess]](None) - - @deprecated("lastNoSuccess was not thread-safe and will be removed in 2.11.0", "2.10.0") - def lastNoSuccess: NoSuccess = lastNoSuccessVar.value.orNull - - @deprecated("lastNoSuccess was not thread-safe and will be removed in 2.11.0", "2.10.0") - def lastNoSuccess_=(x: NoSuccess): Unit = lastNoSuccessVar.value = Option(x) - - /** A common super-class for unsuccessful parse results. */ - sealed abstract class NoSuccess(val msg: String, override val next: Input) extends ParseResult[Nothing] { // when we don't care about the difference between Failure and Error - val successful = false - - if (lastNoSuccessVar.value forall (v => !(next.pos < v.next.pos))) - lastNoSuccessVar.value = Some(this) - - def map[U](f: Nothing => U) = this - def mapPartial[U](f: PartialFunction[Nothing, U], error: Nothing => String): ParseResult[U] = this - - def flatMapWithNext[U](f: Nothing => Input => ParseResult[U]): ParseResult[U] - = this - - def filterWithError(p: Nothing => Boolean, error: Nothing => String, position: Input): ParseResult[Nothing] = this - - def get: Nothing = scala.sys.error("No result when parsing failed") - } - /** An extractor so `NoSuccess(msg, next)` can be used in matches. */ - object NoSuccess { - def unapply[T](x: ParseResult[T]) = x match { - case Failure(msg, next) => Some((msg, next)) - case Error(msg, next) => Some((msg, next)) - case _ => None - } - } - - /** The failure case of `ParseResult`: contains an error-message and the remaining input. - * Parsing will back-track when a failure occurs. - * - * @param msg An error message string describing the failure. - * @param next The parser's unconsumed input at the point where the failure occurred. - */ - case class Failure(override val msg: String, override val next: Input) extends NoSuccess(msg, next) { - /** The toString method of a Failure yields an error message. */ - override def toString = "["+next.pos+"] failure: "+msg+"\n\n"+next.pos.longString - - def append[U >: Nothing](a: => ParseResult[U]): ParseResult[U] = { val alt = a; alt match { - case Success(_, _) => alt - case ns: NoSuccess => if (alt.next.pos < next.pos) this else alt - }} - } - - /** The fatal failure case of ParseResult: contains an error-message and - * the remaining input. - * No back-tracking is done when a parser returns an `Error`. - * - * @param msg An error message string describing the error. - * @param next The parser's unconsumed input at the point where the error occurred. - */ - case class Error(override val msg: String, override val next: Input) extends NoSuccess(msg, next) { - /** The toString method of an Error yields an error message. */ - override def toString = "["+next.pos+"] error: "+msg+"\n\n"+next.pos.longString - def append[U >: Nothing](a: => ParseResult[U]): ParseResult[U] = this - } - - def Parser[T](f: Input => ParseResult[T]): Parser[T] - = new Parser[T]{ def apply(in: Input) = f(in) } - - def OnceParser[T](f: Input => ParseResult[T]): Parser[T] with OnceParser[T] - = new Parser[T] with OnceParser[T] { def apply(in: Input) = f(in) } - - /** The root class of parsers. - * Parsers are functions from the Input type to ParseResult. - */ - abstract class Parser[+T] extends (Input => ParseResult[T]) { - private var name: String = "" - def named(n: String): this.type = {name=n; this} - override def toString() = "Parser ("+ name +")" - - /** An unspecified method that defines the behaviour of this parser. */ - def apply(in: Input): ParseResult[T] - - def flatMap[U](f: T => Parser[U]): Parser[U] - = Parser{ in => this(in) flatMapWithNext(f)} - - def map[U](f: T => U): Parser[U] //= flatMap{x => success(f(x))} - = Parser{ in => this(in) map(f)} - - def filter(p: T => Boolean): Parser[T] - = withFilter(p) - - def withFilter(p: T => Boolean): Parser[T] - = Parser{ in => this(in) filterWithError(p, "Input doesn't match filter: "+_, in)} - - // no filter yet, dealing with zero is tricky! - - @migration("The call-by-name argument is evaluated at most once per constructed Parser object, instead of on every need that arises during parsing.", "2.9.0") - def append[U >: T](p0: => Parser[U]): Parser[U] = { lazy val p = p0 // lazy argument - Parser{ in => this(in) append p(in)} - } - - // the operator formerly known as +++, ++, &, but now, behold the venerable ~ - // it's short, light (looks like whitespace), has few overloaded meaning (thanks to the recent change from ~ to unary_~) - // and we love it! (or do we like `,` better?) - - /** A parser combinator for sequential composition. - * - * `p ~ q` succeeds if `p` succeeds and `q` succeeds on the input left over by `p`. - * - * @param q a parser that will be executed after `p` (this parser) - * succeeds -- evaluated at most once, and only when necessary. - * @return a `Parser` that -- on success -- returns a `~` (like a `Pair`, - * but easier to pattern match on) that contains the result of `p` and - * that of `q`. The resulting parser fails if either `p` or `q` fails. - */ - @migration("The call-by-name argument is evaluated at most once per constructed Parser object, instead of on every need that arises during parsing.", "2.9.0") - def ~ [U](q: => Parser[U]): Parser[~[T, U]] = { lazy val p = q // lazy argument - (for(a <- this; b <- p) yield new ~(a,b)).named("~") - } - - /** A parser combinator for sequential composition which keeps only the right result. - * - * `p ~> q` succeeds if `p` succeeds and `q` succeeds on the input left over by `p`. - * - * @param q a parser that will be executed after `p` (this parser) - * succeeds -- evaluated at most once, and only when necessary. - * @return a `Parser` that -- on success -- returns the result of `q`. - */ - @migration("The call-by-name argument is evaluated at most once per constructed Parser object, instead of on every need that arises during parsing.", "2.9.0") - def ~> [U](q: => Parser[U]): Parser[U] = { lazy val p = q // lazy argument - (for(a <- this; b <- p) yield b).named("~>") - } - - /** A parser combinator for sequential composition which keeps only the left result. - * - * `p <~ q` succeeds if `p` succeeds and `q` succeeds on the input - * left over by `p`. - * - * @note <~ has lower operator precedence than ~ or ~>. - * - * @param q a parser that will be executed after `p` (this parser) succeeds -- evaluated at most once, and only when necessary - * @return a `Parser` that -- on success -- returns the result of `p`. - */ - @migration("The call-by-name argument is evaluated at most once per constructed Parser object, instead of on every need that arises during parsing.", "2.9.0") - def <~ [U](q: => Parser[U]): Parser[T] = { lazy val p = q // lazy argument - (for(a <- this; b <- p) yield a).named("<~") - } - - /* not really useful: V cannot be inferred because Parser is covariant in first type parameter (V is always trivially Nothing) - def ~~ [U, V](q: => Parser[U])(implicit combine: (T, U) => V): Parser[V] = new Parser[V] { - def apply(in: Input) = seq(Parser.this, q)((x, y) => combine(x,y))(in) - } */ - - /** A parser combinator for non-back-tracking sequential composition. - * - * `p ~! q` succeeds if `p` succeeds and `q` succeeds on the input left over by `p`. - * In case of failure, no back-tracking is performed (in an earlier parser produced by the `|` combinator). - * - * @param p a parser that will be executed after `p` (this parser) succeeds - * @return a `Parser` that -- on success -- returns a `~` (like a Pair, but easier to pattern match on) - * that contains the result of `p` and that of `q`. - * The resulting parser fails if either `p` or `q` fails, this failure is fatal. - */ - def ~! [U](p: => Parser[U]): Parser[~[T, U]] - = OnceParser{ (for(a <- this; b <- commit(p)) yield new ~(a,b)).named("~!") } - - /** A parser combinator for alternative composition. - * - * `p | q` succeeds if `p` succeeds or `q` succeeds. - * Note that `q` is only tried if `p`s failure is non-fatal (i.e., back-tracking is allowed). - * - * @param q a parser that will be executed if `p` (this parser) fails (and allows back-tracking) - * @return a `Parser` that returns the result of the first parser to succeed (out of `p` and `q`) - * The resulting parser succeeds if (and only if) - * - `p` succeeds, ''or'' - * - if `p` fails allowing back-tracking and `q` succeeds. - */ - def | [U >: T](q: => Parser[U]): Parser[U] = append(q).named("|") - - // TODO - /** A parser combinator for alternative with longest match composition. - * - * `p ||| q` succeeds if `p` succeeds or `q` succeeds. - * If `p` and `q` both succeed, the parser that consumed the most characters accepts. - * - * @param q0 a parser that accepts if p consumes less characters. -- evaluated at most once, and only when necessary - * @return a `Parser` that returns the result of the parser consuming the most characters (out of `p` and `q`). - */ - @migration("The call-by-name argument is evaluated at most once per constructed Parser object, instead of on every need that arises during parsing.", "2.9.0") - def ||| [U >: T](q0: => Parser[U]): Parser[U] = new Parser[U] { - lazy val q = q0 // lazy argument - def apply(in: Input) = { - val res1 = Parser.this(in) - val res2 = q(in) - - (res1, res2) match { - case (s1 @ Success(_, next1), s2 @ Success(_, next2)) => if (next2.pos < next1.pos) s1 else s2 - case (s1 @ Success(_, _), _) => s1 - case (_, s2 @ Success(_, _)) => s2 - case (e1 @ Error(_, _), _) => e1 - case (f1 @ Failure(_, next1), ns2 @ NoSuccess(_, next2)) => if (next2.pos < next1.pos) f1 else ns2 - } - } - override def toString = "|||" - } - - /** A parser combinator for function application. - * - * `p ^^ f` succeeds if `p` succeeds; it returns `f` applied to the result of `p`. - * - * @param f a function that will be applied to this parser's result (see `map` in `ParseResult`). - * @return a parser that has the same behaviour as the current parser, but whose result is - * transformed by `f`. - */ - def ^^ [U](f: T => U): Parser[U] = map(f).named(toString+"^^") - - /** A parser combinator that changes a successful result into the specified value. - * - * `p ^^^ v` succeeds if `p` succeeds; discards its result, and returns `v` instead. - * - * @param v The new result for the parser, evaluated at most once (if `p` succeeds), not evaluated at all if `p` fails. - * @return a parser that has the same behaviour as the current parser, but whose successful result is `v` - */ - @migration("The call-by-name argument is evaluated at most once per constructed Parser object, instead of on every need that arises during parsing.", "2.9.0") - def ^^^ [U](v: => U): Parser[U] = new Parser[U] { - lazy val v0 = v // lazy argument - def apply(in: Input) = Parser.this(in) map (x => v0) - }.named(toString+"^^^") - - /** A parser combinator for partial function application. - * - * `p ^? (f, error)` succeeds if `p` succeeds AND `f` is defined at the result of `p`; - * in that case, it returns `f` applied to the result of `p`. If `f` is not applicable, - * error(the result of `p`) should explain why. - * - * @param f a partial function that will be applied to this parser's result - * (see `mapPartial` in `ParseResult`). - * @param error a function that takes the same argument as `f` and produces an error message - * to explain why `f` wasn't applicable - * @return a parser that succeeds if the current parser succeeds <i>and</i> `f` is applicable - * to the result. If so, the result will be transformed by `f`. - */ - def ^? [U](f: PartialFunction[T, U], error: T => String): Parser[U] = Parser{ in => - this(in).mapPartial(f, error)}.named(toString+"^?") - - /** A parser combinator for partial function application. - * - * `p ^? f` succeeds if `p` succeeds AND `f` is defined at the result of `p`; - * in that case, it returns `f` applied to the result of `p`. - * - * @param f a partial function that will be applied to this parser's result - * (see `mapPartial` in `ParseResult`). - * @return a parser that succeeds if the current parser succeeds <i>and</i> `f` is applicable - * to the result. If so, the result will be transformed by `f`. - */ - def ^? [U](f: PartialFunction[T, U]): Parser[U] = ^?(f, r => "Constructor function not defined at "+r) - - /** A parser combinator that parameterizes a subsequent parser with the - * result of this one. - * - * Use this combinator when a parser depends on the result of a previous - * parser. `p` should be a function that takes the result from the first - * parser and returns the second parser. - * - * `p into fq` (with `fq` typically `{x => q}`) first applies `p`, and - * then, if `p` successfully returned result `r`, applies `fq(r)` to the - * rest of the input. - * - * ''From: G. Hutton. Higher-order functions for parsing. J. Funct. Program., 2(3):323--343, 1992.'' - * - * @example {{{ - * def perlRE = "m" ~> (".".r into (separator => """[^%s]*""".format(separator).r <~ separator)) - * }}} - * - * @param fq a function that, given the result from this parser, returns - * the second parser to be applied - * @return a parser that succeeds if this parser succeeds (with result `x`) - * and if then `fq(x)` succeeds - */ - def into[U](fq: T => Parser[U]): Parser[U] = flatMap(fq) - - // shortcuts for combinators: - - /** Returns `into(fq)`. */ - def >>[U](fq: T => Parser[U])=into(fq) - - /** Returns a parser that repeatedly parses what this parser parses. - * - * @return rep(this) - */ - def * = rep(this) - - /** Returns a parser that repeatedly parses what this parser parses, - * interleaved with the `sep` parser. The `sep` parser specifies how - * the results parsed by this parser should be combined. - * - * @return chainl1(this, sep) - */ - def *[U >: T](sep: => Parser[(U, U) => U]) = chainl1(this, sep) - - // TODO: improve precedence? a ~ b*(",") = a ~ (b*(",")) should be true - - /** Returns a parser that repeatedly (at least once) parses what this parser parses. - * - * @return rep1(this) - */ - def + = rep1(this) - - /** Returns a parser that optionally parses what this parser parses. - * - * @return opt(this) - */ - def ? = opt(this) - - /** Changes the failure message produced by a parser. - * - * This doesn't change the behavior of a parser on neither - * success nor error, just on failure. The semantics are - * slightly different than those obtained by doing `| failure(msg)`, - * in that the message produced by this method will always - * replace the message produced, which is not guaranteed - * by that idiom. - * - * For example, parser `p` below will always produce the - * designated failure message, while `q` will not produce - * it if `sign` is parsed but `number` is not. - * - * {{{ - * def p = sign.? ~ number withFailureMessage "Number expected!" - * def q = sign.? ~ number | failure("Number expected!") - * }}} - * - * @param msg The message that will replace the default failure message. - * @return A parser with the same properties and different failure message. - */ - def withFailureMessage(msg: String) = Parser{ in => - this(in) match { - case Failure(_, next) => Failure(msg, next) - case other => other - } - } - - /** Changes the error message produced by a parser. - * - * This doesn't change the behavior of a parser on neither - * success nor failure, just on error. The semantics are - * slightly different than those obtained by doing `| error(msg)`, - * in that the message produced by this method will always - * replace the message produced, which is not guaranteed - * by that idiom. - * - * For example, parser `p` below will always produce the - * designated error message, while `q` will not produce - * it if `sign` is parsed but `number` is not. - * - * {{{ - * def p = sign.? ~ number withErrorMessage "Number expected!" - * def q = sign.? ~ number | error("Number expected!") - * }}} - * - * @param msg The message that will replace the default error message. - * @return A parser with the same properties and different error message. - */ - def withErrorMessage(msg: String) = Parser{ in => - this(in) match { - case Error(_, next) => Error(msg, next) - case other => other - } - } - } - - /** Wrap a parser so that its failures become errors (the `|` combinator - * will give up as soon as it encounters an error, on failure it simply - * tries the next alternative). - */ - def commit[T](p: => Parser[T]) = Parser{ in => - p(in) match{ - case s @ Success(_, _) => s - case e @ Error(_, _) => e - case f @ Failure(msg, next) => Error(msg, next) - } - } - - /*trait ElemFun - case class EFCons(hd: Elem => ElemFun, tl: ElemFun) extends ElemFun - case class EFNil(res: Boolean) extends ElemFun*/ - - /** A parser matching input elements that satisfy a given predicate. - * - * `elem(kind, p)` succeeds if the input starts with an element `e` for which `p(e)` is true. - * - * @param kind The element kind, used for error messages - * @param p A predicate that determines which elements match. - * @return - */ - def elem(kind: String, p: Elem => Boolean) = acceptIf(p)(inEl => kind+" expected") - - /** A parser that matches only the given element `e`. - * - * `elem(e)` succeeds if the input starts with an element `e`. - * - * @param e the `Elem` that must be the next piece of input for the returned parser to succeed - * @return a `Parser` that succeeds if `e` is the next available input (and returns it). - */ - def elem(e: Elem): Parser[Elem] = accept(e) - - /** A parser that matches only the given element `e`. - * - * The method is implicit so that elements can automatically be lifted to their parsers. - * For example, when parsing `Token`s, `Identifier("new")` (which is a `Token`) can be used directly, - * instead of first creating a `Parser` using `accept(Identifier("new"))`. - * - * @param e the `Elem` that must be the next piece of input for the returned parser to succeed - * @return a `tParser` that succeeds if `e` is the next available input. - */ - - implicit def accept(e: Elem): Parser[Elem] = acceptIf(_ == e)("`"+e+"' expected but " + _ + " found") - - /** A parser that matches only the given list of element `es`. - * - * `accept(es)` succeeds if the input subsequently provides the elements in the list `es`. - * - * @param es the list of expected elements - * @return a Parser that recognizes a specified list of elements - */ - def accept[ES <% List[Elem]](es: ES): Parser[List[Elem]] = acceptSeq(es) - - /** The parser that matches an element in the domain of the partial function `f`. - * - * If `f` is defined on the first element in the input, `f` is applied - * to it to produce this parser's result. - * - * Example: The parser `accept("name", {case Identifier(n) => Name(n)})` - * accepts an `Identifier(n)` and returns a `Name(n)` - * - * @param expected a description of the kind of element this parser expects (for error messages) - * @param f a partial function that determines when this parser is successful and what its output is - * @return A parser that succeeds if `f` is applicable to the first element of the input, - * applying `f` to it to produce the result. - */ - def accept[U](expected: String, f: PartialFunction[Elem, U]): Parser[U] = acceptMatch(expected, f) - - /** A parser matching input elements that satisfy a given predicate. - * - * `acceptIf(p)(el => "Unexpected "+el)` succeeds if the input starts with an element `e` for which `p(e)` is true. - * - * @param err A function from the received element into an error message. - * @param p A predicate that determines which elements match. - * @return A parser for elements satisfying p(e). - */ - def acceptIf(p: Elem => Boolean)(err: Elem => String): Parser[Elem] = Parser { in => - if (in.atEnd) Failure("end of input", in) - else if (p(in.first)) Success(in.first, in.rest) - else Failure(err(in.first), in) - } - - /** The parser that matches an element in the domain of the partial function `f`. - * - * If `f` is defined on the first element in the input, `f` is applied - * to it to produce this parser's result. - * - * Example: The parser `acceptMatch("name", {case Identifier(n) => Name(n)})` - * accepts an `Identifier(n)` and returns a `Name(n)` - * - * @param expected a description of the kind of element this parser expects (for error messages) - * @param f a partial function that determines when this parser is successful and what its output is - * @return A parser that succeeds if `f` is applicable to the first element of the input, - * applying `f` to it to produce the result. - */ - def acceptMatch[U](expected: String, f: PartialFunction[Elem, U]): Parser[U] = Parser{ in => - if (in.atEnd) Failure("end of input", in) - else if (f.isDefinedAt(in.first)) Success(f(in.first), in.rest) - else Failure(expected+" expected", in) - } - - /** A parser that matches only the given [[scala.collection.Iterable]] collection of elements `es`. - * - * `acceptSeq(es)` succeeds if the input subsequently provides the elements in the iterable `es`. - * - * @param es the list of expected elements - * @return a Parser that recognizes a specified list of elements - */ - def acceptSeq[ES <% Iterable[Elem]](es: ES): Parser[List[Elem]] = - es.foldRight[Parser[List[Elem]]](success(Nil)){(x, pxs) => accept(x) ~ pxs ^^ mkList} - - /** A parser that always fails. - * - * @param msg The error message describing the failure. - * @return A parser that always fails with the specified error message. - */ - def failure(msg: String) = Parser{ in => Failure(msg, in) } - - /** A parser that results in an error. - * - * @param msg The error message describing the failure. - * @return A parser that always fails with the specified error message. - */ - def err(msg: String) = Parser{ in => Error(msg, in) } - - /** A parser that always succeeds. - * - * @param v The result for the parser - * @return A parser that always succeeds, with the given result `v` - */ - def success[T](v: T) = Parser{ in => Success(v, in) } - - /** A helper method that turns a `Parser` into one that will - * print debugging information to stdout before and after - * being applied. - */ - def log[T](p: => Parser[T])(name: String): Parser[T] = Parser{ in => - println("trying "+ name +" at "+ in) - val r = p(in) - println(name +" --> "+ r) - r - } - - /** A parser generator for repetitions. - * - * `rep(p)` repeatedly uses `p` to parse the input until `p` fails - * (the result is a List of the consecutive results of `p`). - * - * @param p a `Parser` that is to be applied successively to the input - * @return A parser that returns a list of results produced by repeatedly applying `p` to the input. - */ - def rep[T](p: => Parser[T]): Parser[List[T]] = rep1(p) | success(List()) - - /** A parser generator for interleaved repetitions. - * - * `repsep(p, q)` repeatedly uses `p` interleaved with `q` to parse the input, until `p` fails. - * (The result is a `List` of the results of `p`.) - * - * Example: `repsep(term, ",")` parses a comma-separated list of term's, yielding a list of these terms. - * - * @param p a `Parser` that is to be applied successively to the input - * @param q a `Parser` that parses the elements that separate the elements parsed by `p` - * @return A parser that returns a list of results produced by repeatedly applying `p` (interleaved with `q`) to the input. - * The results of `p` are collected in a list. The results of `q` are discarded. - */ - def repsep[T](p: => Parser[T], q: => Parser[Any]): Parser[List[T]] = - rep1sep(p, q) | success(List()) - - /** A parser generator for non-empty repetitions. - * - * `rep1(p)` repeatedly uses `p` to parse the input until `p` fails -- `p` must succeed at least - * once (the result is a `List` of the consecutive results of `p`) - * - * @param p a `Parser` that is to be applied successively to the input - * @return A parser that returns a list of results produced by repeatedly applying `p` to the input - * (and that only succeeds if `p` matches at least once). - */ - def rep1[T](p: => Parser[T]): Parser[List[T]] = rep1(p, p) - - /** A parser generator for non-empty repetitions. - * - * `rep1(f, p)` first uses `f` (which must succeed) and then repeatedly - * uses `p` to parse the input until `p` fails - * (the result is a `List` of the consecutive results of `f` and `p`) - * - * @param first a `Parser` that parses the first piece of input - * @param p0 a `Parser` that is to be applied successively to the rest of the input (if any) -- evaluated at most once, and only when necessary - * @return A parser that returns a list of results produced by first applying `f` and then - * repeatedly `p` to the input (it only succeeds if `f` matches). - */ - @migration("The `p0` call-by-name arguments is evaluated at most once per constructed Parser object, instead of on every need that arises during parsing.", "2.9.0") - def rep1[T](first: => Parser[T], p0: => Parser[T]): Parser[List[T]] = Parser { in => - lazy val p = p0 // lazy argument - val elems = new ListBuffer[T] - - def continue(in: Input): ParseResult[List[T]] = { - val p0 = p // avoid repeatedly re-evaluating by-name parser - @tailrec def applyp(in0: Input): ParseResult[List[T]] = p0(in0) match { - case Success(x, rest) => elems += x ; applyp(rest) - case e @ Error(_, _) => e // still have to propagate error - case _ => Success(elems.toList, in0) - } - - applyp(in) - } - - first(in) match { - case Success(x, rest) => elems += x ; continue(rest) - case ns: NoSuccess => ns - } - } - - /** A parser generator for a specified number of repetitions. - * - * `repN(n, p)` uses `p` exactly `n` time to parse the input - * (the result is a `List` of the `n` consecutive results of `p`). - * - * @param p a `Parser` that is to be applied successively to the input - * @param num the exact number of times `p` must succeed - * @return A parser that returns a list of results produced by repeatedly applying `p` to the input - * (and that only succeeds if `p` matches exactly `n` times). - */ - def repN[T](num: Int, p: => Parser[T]): Parser[List[T]] = - if (num == 0) success(Nil) else Parser { in => - val elems = new ListBuffer[T] - val p0 = p // avoid repeatedly re-evaluating by-name parser - - @tailrec def applyp(in0: Input): ParseResult[List[T]] = - if (elems.length == num) Success(elems.toList, in0) - else p0(in0) match { - case Success(x, rest) => elems += x ; applyp(rest) - case ns: NoSuccess => return ns - } - - applyp(in) - } - - /** A parser generator for non-empty repetitions. - * - * `rep1sep(p, q)` repeatedly applies `p` interleaved with `q` to parse the - * input, until `p` fails. The parser `p` must succeed at least once. - * - * @param p a `Parser` that is to be applied successively to the input - * @param q a `Parser` that parses the elements that separate the elements parsed by `p` - * (interleaved with `q`) - * @return A parser that returns a list of results produced by repeatedly applying `p` to the input - * (and that only succeeds if `p` matches at least once). - * The results of `p` are collected in a list. The results of `q` are discarded. - */ - def rep1sep[T](p : => Parser[T], q : => Parser[Any]): Parser[List[T]] = - p ~ rep(q ~> p) ^^ {case x~y => x::y} - - /** A parser generator that, roughly, generalises the rep1sep generator so - * that `q`, which parses the separator, produces a left-associative - * function that combines the elements it separates. - * - * ''From: J. Fokker. Functional parsers. In J. Jeuring and E. Meijer, editors, Advanced Functional Programming, - * volume 925 of Lecture Notes in Computer Science, pages 1--23. Springer, 1995.'' - * - * @param p a parser that parses the elements - * @param q a parser that parses the token(s) separating the elements, yielding a left-associative function that - * combines two elements into one - */ - def chainl1[T](p: => Parser[T], q: => Parser[(T, T) => T]): Parser[T] - = chainl1(p, p, q) - - /** A parser generator that, roughly, generalises the `rep1sep` generator - * so that `q`, which parses the separator, produces a left-associative - * function that combines the elements it separates. - * - * @param first a parser that parses the first element - * @param p a parser that parses the subsequent elements - * @param q a parser that parses the token(s) separating the elements, - * yielding a left-associative function that combines two elements - * into one - */ - def chainl1[T, U](first: => Parser[T], p: => Parser[U], q: => Parser[(T, U) => T]): Parser[T] - = first ~ rep(q ~ p) ^^ { - case x ~ xs => xs.foldLeft(x: T){case (a, f ~ b) => f(a, b)} // x's type annotation is needed to deal with changed type inference due to SI-5189 - } - - /** A parser generator that generalises the `rep1sep` generator so that `q`, - * which parses the separator, produces a right-associative function that - * combines the elements it separates. Additionally, the right-most (last) - * element and the left-most combining function have to be supplied. - * - * rep1sep(p: Parser[T], q) corresponds to chainr1(p, q ^^ cons, cons, Nil) (where val cons = (x: T, y: List[T]) => x :: y) - * - * @param p a parser that parses the elements - * @param q a parser that parses the token(s) separating the elements, yielding a right-associative function that - * combines two elements into one - * @param combine the "last" (left-most) combination function to be applied - * @param first the "first" (right-most) element to be combined - */ - def chainr1[T, U](p: => Parser[T], q: => Parser[(T, U) => U], combine: (T, U) => U, first: U): Parser[U] - = p ~ rep(q ~ p) ^^ { - case x ~ xs => (new ~(combine, x) :: xs).foldRight(first){case (f ~ a, b) => f(a, b)} - } - - /** A parser generator for optional sub-phrases. - * - * `opt(p)` is a parser that returns `Some(x)` if `p` returns `x` and `None` if `p` fails. - * - * @param p A `Parser` that is tried on the input - * @return a `Parser` that always succeeds: either with the result provided by `p` or - * with the empty result - */ - def opt[T](p: => Parser[T]): Parser[Option[T]] = - p ^^ (x => Some(x)) | success(None) - - /** Wrap a parser so that its failures and errors become success and - * vice versa -- it never consumes any input. - */ - def not[T](p: => Parser[T]): Parser[Unit] = Parser { in => - p(in) match { - case Success(_, _) => Failure("Expected failure", in) - case _ => Success((), in) - } - } - - /** A parser generator for guard expressions. The resulting parser will - * fail or succeed just like the one given as parameter but it will not - * consume any input. - * - * @param p a `Parser` that is to be applied to the input - * @return A parser that returns success if and only if `p` succeeds but - * never consumes any input - */ - def guard[T](p: => Parser[T]): Parser[T] = Parser { in => - p(in) match{ - case s@ Success(s1,_) => Success(s1, in) - case e => e - } - } - - /** `positioned` decorates a parser's result with the start position of the - * input it consumed. - * - * @param p a `Parser` whose result conforms to `Positional`. - * @return A parser that has the same behaviour as `p`, but which marks its - * result with the start position of the input it consumed, - * if it didn't already have a position. - */ - def positioned[T <: Positional](p: => Parser[T]): Parser[T] = Parser { in => - p(in) match { - case Success(t, in1) => Success(if (t.pos == NoPosition) t setPos in.pos else t, in1) - case ns: NoSuccess => ns - } - } - - /** A parser generator delimiting whole phrases (i.e. programs). - * - * `phrase(p)` succeeds if `p` succeeds and no input is left over after `p`. - * - * @param p the parser that must consume all input for the resulting parser - * to succeed. - * @return a parser that has the same result as `p`, but that only succeeds - * if `p` consumed all the input. - */ - def phrase[T](p: Parser[T]) = new Parser[T] { - def apply(in: Input) = lastNoSuccessVar.withValue(None) { - p(in) match { - case s @ Success(out, in1) => - if (in1.atEnd) - s - else - lastNoSuccessVar.value filterNot { _.next.pos < in1.pos } getOrElse Failure("end of input expected", in1) - case ns => lastNoSuccessVar.value.getOrElse(ns) - } - } - } - - /** Given a concatenation with a repetition (list), move the concatenated element into the list */ - def mkList[T] = (_: ~[T, List[T]]) match { case x ~ xs => x :: xs } - - /** A wrapper over sequence of matches. - * - * Given `p1: Parser[A]` and `p2: Parser[B]`, a parser composed with - * `p1 ~ p2` will have type `Parser[~[A, B]]`. The successful result - * of the parser can be extracted from this case class. - * - * It also enables pattern matching, so something like this is possible: - * - * {{{ - * def concat(p1: Parser[String], p2: Parser[String]): Parser[String] = - * p1 ~ p2 ^^ { case a ~ b => a + b } - * }}} - */ - case class ~[+a, +b](_1: a, _2: b) { - override def toString = "("+ _1 +"~"+ _2 +")" - } - - /** A parser whose `~` combinator disallows back-tracking. - */ - trait OnceParser[+T] extends Parser[T] { - override def ~ [U](p: => Parser[U]): Parser[~[T, U]] - = OnceParser{ (for(a <- this; b <- commit(p)) yield new ~(a,b)).named("~") } - } -} diff --git a/src/library/scala/util/parsing/combinator/RegexParsers.scala b/src/library/scala/util/parsing/combinator/RegexParsers.scala deleted file mode 100644 index d17d0cac8d..0000000000 --- a/src/library/scala/util/parsing/combinator/RegexParsers.scala +++ /dev/null @@ -1,165 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2006-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - -package scala.util.parsing.combinator - -import java.util.regex.Pattern -import scala.util.matching.Regex -import scala.util.parsing.input._ -import scala.collection.immutable.PagedSeq -import scala.language.implicitConversions - -/** The ''most important'' differences between `RegexParsers` and - * [[scala.util.parsing.combinator.Parsers]] are: - * - * - `Elem` is defined to be [[scala.Char]] - * - There's an implicit conversion from [[java.lang.String]] to `Parser[String]`, - * so that string literals can be used as parser combinators. - * - There's an implicit conversion from [[scala.util.matching.Regex]] to `Parser[String]`, - * so that regex expressions can be used as parser combinators. - * - The parsing methods call the method `skipWhitespace` (defaults to `true`) and, if true, - * skip any whitespace before each parser is called. - * - Protected val `whiteSpace` returns a regex that identifies whitespace. - * - * For example, this creates a very simple calculator receiving `String` input: - * - * {{{ - * object Calculator extends RegexParsers { - * def number: Parser[Double] = """\d+(\.\d*)?""".r ^^ { _.toDouble } - * def factor: Parser[Double] = number | "(" ~> expr <~ ")" - * def term : Parser[Double] = factor ~ rep( "*" ~ factor | "/" ~ factor) ^^ { - * case number ~ list => (number /: list) { - * case (x, "*" ~ y) => x * y - * case (x, "/" ~ y) => x / y - * } - * } - * def expr : Parser[Double] = term ~ rep("+" ~ log(term)("Plus term") | "-" ~ log(term)("Minus term")) ^^ { - * case number ~ list => list.foldLeft(number) { // same as before, using alternate name for /: - * case (x, "+" ~ y) => x + y - * case (x, "-" ~ y) => x - y - * } - * } - * - * def apply(input: String): Double = parseAll(expr, input) match { - * case Success(result, _) => result - * case failure : NoSuccess => scala.sys.error(failure.msg) - * } - * } - * }}} - */ -trait RegexParsers extends Parsers { - - type Elem = Char - - protected val whiteSpace = """\s+""".r - - def skipWhitespace = whiteSpace.toString.length > 0 - - /** Method called to handle whitespace before parsers. - * - * It checks `skipWhitespace` and, if true, skips anything - * matching `whiteSpace` starting from the current offset. - * - * @param source The input being parsed. - * @param offset The offset into `source` from which to match. - * @return The offset to be used for the next parser. - */ - protected def handleWhiteSpace(source: java.lang.CharSequence, offset: Int): Int = - if (skipWhitespace) - (whiteSpace findPrefixMatchOf (source.subSequence(offset, source.length))) match { - case Some(matched) => offset + matched.end - case None => offset - } - else - offset - - /** A parser that matches a literal string */ - implicit def literal(s: String): Parser[String] = new Parser[String] { - def apply(in: Input) = { - val source = in.source - val offset = in.offset - val start = handleWhiteSpace(source, offset) - var i = 0 - var j = start - while (i < s.length && j < source.length && s.charAt(i) == source.charAt(j)) { - i += 1 - j += 1 - } - if (i == s.length) - Success(source.subSequence(start, j).toString, in.drop(j - offset)) - else { - val found = if (start == source.length()) "end of source" else "`"+source.charAt(start)+"'" - Failure("`"+s+"' expected but "+found+" found", in.drop(start - offset)) - } - } - } - - /** A parser that matches a regex string */ - implicit def regex(r: Regex): Parser[String] = new Parser[String] { - def apply(in: Input) = { - val source = in.source - val offset = in.offset - val start = handleWhiteSpace(source, offset) - (r findPrefixMatchOf (source.subSequence(start, source.length))) match { - case Some(matched) => - Success(source.subSequence(start, start + matched.end).toString, - in.drop(start + matched.end - offset)) - case None => - val found = if (start == source.length()) "end of source" else "`"+source.charAt(start)+"'" - Failure("string matching regex `"+r+"' expected but "+found+" found", in.drop(start - offset)) - } - } - } - - /** `positioned` decorates a parser's result with the start position of the input it consumed. - * If whitespace is being skipped, then it is skipped before the start position is recorded. - * - * @param p a `Parser` whose result conforms to `Positional`. - * @return A parser that has the same behaviour as `p`, but which marks its result with the - * start position of the input it consumed after whitespace has been skipped, if it - * didn't already have a position. - */ - override def positioned[T <: Positional](p: => Parser[T]): Parser[T] = { - val pp = super.positioned(p) - new Parser[T] { - def apply(in: Input) = { - val offset = in.offset - val start = handleWhiteSpace(in.source, offset) - pp(in.drop (start - offset)) - } - } - } - - override def phrase[T](p: Parser[T]): Parser[T] = - super.phrase(p <~ opt("""\z""".r)) - - /** Parse some prefix of reader `in` with parser `p`. */ - def parse[T](p: Parser[T], in: Reader[Char]): ParseResult[T] = - p(in) - - /** Parse some prefix of character sequence `in` with parser `p`. */ - def parse[T](p: Parser[T], in: java.lang.CharSequence): ParseResult[T] = - p(new CharSequenceReader(in)) - - /** Parse some prefix of reader `in` with parser `p`. */ - def parse[T](p: Parser[T], in: java.io.Reader): ParseResult[T] = - p(new PagedSeqReader(PagedSeq.fromReader(in))) - - /** Parse all of reader `in` with parser `p`. */ - def parseAll[T](p: Parser[T], in: Reader[Char]): ParseResult[T] = - parse(phrase(p), in) - - /** Parse all of reader `in` with parser `p`. */ - def parseAll[T](p: Parser[T], in: java.io.Reader): ParseResult[T] = - parse(phrase(p), in) - - /** Parse all of character sequence `in` with parser `p`. */ - def parseAll[T](p: Parser[T], in: java.lang.CharSequence): ParseResult[T] = - parse(phrase(p), in) -} diff --git a/src/library/scala/util/parsing/combinator/lexical/Lexical.scala b/src/library/scala/util/parsing/combinator/lexical/Lexical.scala deleted file mode 100644 index c25c97278f..0000000000 --- a/src/library/scala/util/parsing/combinator/lexical/Lexical.scala +++ /dev/null @@ -1,39 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2006-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - - -package scala.util.parsing -package combinator -package lexical - -import token._ -import input.CharArrayReader.EofCh - -/** This component complements the `Scanners` component with - * common operations for lexical parsers. - * - * Refer to [[scala.util.parsing.combinator.lexical.StdLexical]] - * for a concrete implementation for a simple, Scala-like language. - * - * @author Martin Odersky, Adriaan Moors - */ -abstract class Lexical extends Scanners with Tokens { - - /** A character-parser that matches a letter (and returns it).*/ - def letter = elem("letter", _.isLetter) - - /** A character-parser that matches a digit (and returns it).*/ - def digit = elem("digit", _.isDigit) - - /** A character-parser that matches any character except the ones given in `cs` (and returns it).*/ - def chrExcept(cs: Char*) = elem("", ch => (cs forall (ch != _))) - - /** A character-parser that matches a white-space character (and returns it).*/ - def whitespaceChar = elem("space char", ch => ch <= ' ' && ch != EofCh) -} diff --git a/src/library/scala/util/parsing/combinator/lexical/Scanners.scala b/src/library/scala/util/parsing/combinator/lexical/Scanners.scala deleted file mode 100644 index 5c23ad70cd..0000000000 --- a/src/library/scala/util/parsing/combinator/lexical/Scanners.scala +++ /dev/null @@ -1,65 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2006-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - - -package scala.util.parsing -package combinator -package lexical - -import token._ -import input._ - -/** This component provides core functionality for lexical parsers. - * - * See its subclasses [[scala.util.parsing.combinator.lexical.Lexical]] and -- most interestingly - * [[scala.util.parsing.combinator.lexical.StdLexical]], for more functionality. - * - * @author Martin Odersky, Adriaan Moors - */ -trait Scanners extends Parsers { - type Elem = Char - type Token - - /** This token is produced by a scanner `Scanner` when scanning failed. */ - def errorToken(msg: String): Token - - /** A parser that produces a token (from a stream of characters). */ - def token: Parser[Token] - - /** A parser for white-space -- its result will be discarded. */ - def whitespace: Parser[Any] - - /** `Scanner` is essentially¹ a parser that produces `Token`s - * from a stream of characters. The tokens it produces are typically - * passed to parsers in `TokenParsers`. - * - * @note ¹ `Scanner` is really a `Reader` of `Token`s - */ - class Scanner(in: Reader[Char]) extends Reader[Token] { - /** Convenience constructor (makes a character reader out of the given string) */ - def this(in: String) = this(new CharArrayReader(in.toCharArray())) - private val (tok, rest1, rest2) = whitespace(in) match { - case Success(_, in1) => - token(in1) match { - case Success(tok, in2) => (tok, in1, in2) - case ns: NoSuccess => (errorToken(ns.msg), ns.next, skip(ns.next)) - } - case ns: NoSuccess => (errorToken(ns.msg), ns.next, skip(ns.next)) - } - private def skip(in: Reader[Char]) = if (in.atEnd) in else in.rest - - override def source: java.lang.CharSequence = in.source - override def offset: Int = in.offset - def first = tok - def rest = new Scanner(rest2) - def pos = rest1.pos - def atEnd = in.atEnd || (whitespace(in) match { case Success(_, in1) => in1.atEnd case _ => false }) - } -} - diff --git a/src/library/scala/util/parsing/combinator/lexical/StdLexical.scala b/src/library/scala/util/parsing/combinator/lexical/StdLexical.scala deleted file mode 100644 index f3491c096f..0000000000 --- a/src/library/scala/util/parsing/combinator/lexical/StdLexical.scala +++ /dev/null @@ -1,86 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2006-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala.util.parsing -package combinator -package lexical - -import token._ -import input.CharArrayReader.EofCh -import scala.collection.mutable - -/** This component provides a standard lexical parser for a simple, - * [[http://scala-lang.org Scala]]-like language. It parses keywords and - * identifiers, numeric literals (integers), strings, and delimiters. - * - * To distinguish between identifiers and keywords, it uses a set of - * reserved identifiers: every string contained in `reserved` is returned - * as a keyword token. (Note that `=>` is hard-coded as a keyword.) - * Additionally, the kinds of delimiters can be specified by the - * `delimiters` set. - * - * Usually this component is used to break character-based input into - * bigger tokens, which are then passed to a token-parser (see - * [[scala.util.parsing.combinator.syntactical.TokenParsers]].) - * - * @author Martin Odersky - * @author Iulian Dragos - * @author Adriaan Moors - */ -class StdLexical extends Lexical with StdTokens { - // see `token` in `Scanners` - def token: Parser[Token] = - ( identChar ~ rep( identChar | digit ) ^^ { case first ~ rest => processIdent(first :: rest mkString "") } - | digit ~ rep( digit ) ^^ { case first ~ rest => NumericLit(first :: rest mkString "") } - | '\'' ~ rep( chrExcept('\'', '\n', EofCh) ) ~ '\'' ^^ { case '\'' ~ chars ~ '\'' => StringLit(chars mkString "") } - | '\"' ~ rep( chrExcept('\"', '\n', EofCh) ) ~ '\"' ^^ { case '\"' ~ chars ~ '\"' => StringLit(chars mkString "") } - | EofCh ^^^ EOF - | '\'' ~> failure("unclosed string literal") - | '\"' ~> failure("unclosed string literal") - | delim - | failure("illegal character") - ) - - /** Returns the legal identifier chars, except digits. */ - def identChar = letter | elem('_') - - // see `whitespace in `Scanners` - def whitespace: Parser[Any] = rep( - whitespaceChar - | '/' ~ '*' ~ comment - | '/' ~ '/' ~ rep( chrExcept(EofCh, '\n') ) - | '/' ~ '*' ~ failure("unclosed comment") - ) - - protected def comment: Parser[Any] = ( - '*' ~ '/' ^^ { case _ => ' ' } - | chrExcept(EofCh) ~ comment - ) - - /** The set of reserved identifiers: these will be returned as `Keyword`s. */ - val reserved = new mutable.HashSet[String] - - /** The set of delimiters (ordering does not matter). */ - val delimiters = new mutable.HashSet[String] - - protected def processIdent(name: String) = - if (reserved contains name) Keyword(name) else Identifier(name) - - private lazy val _delim: Parser[Token] = { - // construct parser for delimiters by |'ing together the parsers for the individual delimiters, - // starting with the longest one -- otherwise a delimiter D will never be matched if there is - // another delimiter that is a prefix of D - def parseDelim(s: String): Parser[Token] = accept(s.toList) ^^ { x => Keyword(s) } - - val d = new Array[String](delimiters.size) - delimiters.copyToArray(d, 0) - scala.util.Sorting.quickSort(d) - (d.toList map parseDelim).foldRight(failure("no matching delimiter"): Parser[Token])((x, y) => y | x) - } - protected def delim: Parser[Token] = _delim -} diff --git a/src/library/scala/util/parsing/combinator/syntactical/StandardTokenParsers.scala b/src/library/scala/util/parsing/combinator/syntactical/StandardTokenParsers.scala deleted file mode 100644 index d3ae0ea54a..0000000000 --- a/src/library/scala/util/parsing/combinator/syntactical/StandardTokenParsers.scala +++ /dev/null @@ -1,31 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2006-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - -package scala.util.parsing -package combinator -package syntactical - -import token._ -import lexical.StdLexical -import scala.language.implicitConversions - -/** This component provides primitive parsers for the standard tokens defined in `StdTokens`. -* -* @author Martin Odersky, Adriaan Moors - */ -class StandardTokenParsers extends StdTokenParsers { - type Tokens = StdTokens - val lexical = new StdLexical - - //an implicit keyword function that gives a warning when a given word is not in the reserved/delimiters list - override implicit def keyword(chars : String): Parser[String] = - if(lexical.reserved.contains(chars) || lexical.delimiters.contains(chars)) super.keyword(chars) - else failure("You are trying to parse \""+chars+"\", but it is neither contained in the delimiters list, nor in the reserved keyword list of your lexical object") - -} diff --git a/src/library/scala/util/parsing/combinator/syntactical/StdTokenParsers.scala b/src/library/scala/util/parsing/combinator/syntactical/StdTokenParsers.scala deleted file mode 100644 index 7283b01da4..0000000000 --- a/src/library/scala/util/parsing/combinator/syntactical/StdTokenParsers.scala +++ /dev/null @@ -1,51 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2006-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - - -package scala.util.parsing -package combinator -package syntactical - -import token._ -import scala.collection.mutable -import scala.language.implicitConversions - -/** This component provides primitive parsers for the standard tokens defined in `StdTokens`. -* -* @author Martin Odersky, Adriaan Moors - */ -trait StdTokenParsers extends TokenParsers { - type Tokens <: StdTokens - import lexical.{Keyword, NumericLit, StringLit, Identifier} - - protected val keywordCache = mutable.HashMap[String, Parser[String]]() - - /** A parser which matches a single keyword token. - * - * @param chars The character string making up the matched keyword. - * @return a `Parser` that matches the given string - */ -// implicit def keyword(chars: String): Parser[String] = accept(Keyword(chars)) ^^ (_.chars) - implicit def keyword(chars: String): Parser[String] = - keywordCache.getOrElseUpdate(chars, accept(Keyword(chars)) ^^ (_.chars)) - - /** A parser which matches a numeric literal */ - def numericLit: Parser[String] = - elem("number", _.isInstanceOf[NumericLit]) ^^ (_.chars) - - /** A parser which matches a string literal */ - def stringLit: Parser[String] = - elem("string literal", _.isInstanceOf[StringLit]) ^^ (_.chars) - - /** A parser which matches an identifier */ - def ident: Parser[String] = - elem("identifier", _.isInstanceOf[Identifier]) ^^ (_.chars) -} - - diff --git a/src/library/scala/util/parsing/combinator/syntactical/TokenParsers.scala b/src/library/scala/util/parsing/combinator/syntactical/TokenParsers.scala deleted file mode 100644 index 1c4b25b999..0000000000 --- a/src/library/scala/util/parsing/combinator/syntactical/TokenParsers.scala +++ /dev/null @@ -1,34 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2006-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - -package scala.util.parsing -package combinator -package syntactical - -/** This is the core component for token-based parsers. - * - * @author Martin Odersky - * @author Adriaan Moors - */ -trait TokenParsers extends Parsers { - /** `Tokens` is the abstract type of the `Token`s consumed by the parsers in this component. */ - type Tokens <: token.Tokens - - /** `lexical` is the component responsible for consuming some basic kind of - * input (usually character-based) and turning it into the tokens - * understood by these parsers. - */ - val lexical: Tokens - - /** The input-type for these parsers*/ - type Elem = lexical.Token - -} - - diff --git a/src/library/scala/util/parsing/combinator/testing/RegexTest.scala b/src/library/scala/util/parsing/combinator/testing/RegexTest.scala deleted file mode 100644 index 80e9b0df39..0000000000 --- a/src/library/scala/util/parsing/combinator/testing/RegexTest.scala +++ /dev/null @@ -1,27 +0,0 @@ - -package scala.util.parsing.combinator.testing - -import scala.util.parsing.combinator._ -import scala.util.parsing.input._ -import scala.language.postfixOps - -@deprecated("This class will be removed", "2.10.0") -case class Ident(s: String) -@deprecated("This class will be removed", "2.10.0") -case class Number(n: Int) -@deprecated("This class will be removed", "2.10.0") -case class Str(s: String) - -@deprecated("This class will be removed", "2.10.0") -object RegexTest extends RegexParsers { - val ident: Parser[Any] = """[a-zA-Z_]\w*""".r ^^ (s => Ident(s)) - val number: Parser[Any] = """\d\d*""".r ^^ (s => Number(s.toInt)) - val string: Parser[Any] = "\".*\"".r ^^ (s => Str(s.substring(1, s.length - 1))) - val parser = (ident | number | string)* - - def main(args: Array[String]) = { - val in = args mkString " " - println("\nin : "+in) - println(phrase[Any](parser)(new CharSequenceReader(in))) - } -} diff --git a/src/library/scala/util/parsing/combinator/testing/Tester.scala b/src/library/scala/util/parsing/combinator/testing/Tester.scala deleted file mode 100644 index 95730ee292..0000000000 --- a/src/library/scala/util/parsing/combinator/testing/Tester.scala +++ /dev/null @@ -1,45 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2006-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala.util.parsing.combinator.testing -import scala.util.parsing.combinator._ - -import scala.util.parsing.combinator.lexical.Lexical -import scala.util.parsing.combinator.syntactical.TokenParsers - -/** Facilitates testing a given parser on various input strings. - * - * Example use: - * {{{ - * val syntactic = new MyParsers - * }}} - * and - * {{{ - * val parser = syntactic.term - * }}} - * (If `MyParsers` extends [[scala.util.parsing.combinator.syntactical.TokenParsers]] - * with a parser called `term`.) - * - * @author Martin Odersky - * @author Adriaan Moors - */ -@deprecated("This class will be removed", "2.10.0") -abstract class Tester { - - val syntactic: TokenParsers { val lexical: Lexical } - val parser: syntactic.Parser[Any] - - /** Scans a String (using a `syntactic.lexical.Scanner`), parses it using - * `phrase(parser)`, and prints the input and the parsed result to the - * console. - */ - def test(in: String) { - Console.println("\nin : "+in) - Console.println(syntactic.phrase[Any](parser)(new syntactic.lexical.Scanner(in))) - } -} diff --git a/src/library/scala/util/parsing/combinator/token/StdTokens.scala b/src/library/scala/util/parsing/combinator/token/StdTokens.scala deleted file mode 100644 index 605f53bf1d..0000000000 --- a/src/library/scala/util/parsing/combinator/token/StdTokens.scala +++ /dev/null @@ -1,38 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2006-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala.util.parsing -package combinator -package token - -/** This component provides the standard `Token`s for a simple, Scala-like language. - * - * @author Martin Odersky - * @author Adriaan Moors - */ -trait StdTokens extends Tokens { - /** The class of keyword tokens */ - case class Keyword(chars: String) extends Token { - override def toString = "`"+chars+"'" - } - - /** The class of numeric literal tokens */ - case class NumericLit(chars: String) extends Token { - override def toString = chars - } - - /** The class of string literal tokens */ - case class StringLit(chars: String) extends Token { - override def toString = "\""+chars+"\"" - } - - /** The class of identifier tokens */ - case class Identifier(chars: String) extends Token { - override def toString = "identifier "+chars - } -} diff --git a/src/library/scala/util/parsing/combinator/token/Tokens.scala b/src/library/scala/util/parsing/combinator/token/Tokens.scala deleted file mode 100644 index ff92802d77..0000000000 --- a/src/library/scala/util/parsing/combinator/token/Tokens.scala +++ /dev/null @@ -1,42 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2006-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala.util.parsing -package combinator -package token - -/** This component provides the notion of `Token`, the unit of information that is passed from lexical - * parsers in the `Lexical` component to the parsers in the `TokenParsers` component. - * - * @author Martin Odersky - * @author Adriaan Moors - */ -trait Tokens { - /** Objects of this type are produced by a lexical parser or ``scanner'', and consumed by a parser. - * - * @see [[scala.util.parsing.combinator.syntactical.TokenParsers]] - */ - abstract class Token { - def chars: String - } - - /** A class of error tokens. Error tokens are used to communicate - * errors detected during lexical analysis - */ - case class ErrorToken(msg: String) extends Token { - def chars = "*** error: "+msg - } - - /** A class for end-of-file tokens */ - case object EOF extends Token { - def chars = "<eof>" - } - - /** This token is produced by a scanner `Scanner` when scanning failed. */ - def errorToken(msg: String): Token = new ErrorToken(msg) -} diff --git a/src/library/scala/util/parsing/input/CharArrayReader.scala b/src/library/scala/util/parsing/input/CharArrayReader.scala deleted file mode 100644 index 3ba69b229b..0000000000 --- a/src/library/scala/util/parsing/input/CharArrayReader.scala +++ /dev/null @@ -1,34 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2006-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - -package scala.util.parsing.input - -/** An object encapsulating basic character constants. - * - * @author Martin Odersky - * @author Adriaan Moors - */ -object CharArrayReader { - final val EofCh = '\032' -} - -/** A character array reader reads a stream of characters (keeping track of their positions) - * from an array. - * - * @param chars an array of characters - * @param index starting offset into the array; the first element returned will be `source(index)` - * - * @author Martin Odersky - * @author Adriaan Moors - */ -class CharArrayReader(chars: Array[Char], index: Int) extends CharSequenceReader(chars, index) { - - def this(chars: Array[Char]) = this(chars, 0) - -} diff --git a/src/library/scala/util/parsing/input/CharSequenceReader.scala b/src/library/scala/util/parsing/input/CharSequenceReader.scala deleted file mode 100644 index 02aa2ab7b8..0000000000 --- a/src/library/scala/util/parsing/input/CharSequenceReader.scala +++ /dev/null @@ -1,65 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2006-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - -package scala.util.parsing.input - -/** An object encapsulating basic character constants. - * - * @author Martin Odersky, Adriaan Moors - */ -object CharSequenceReader { - final val EofCh = '\032' -} - -/** A character array reader reads a stream of characters (keeping track of their positions) - * from an array. - * - * @param source the source sequence - * @param offset starting offset. - * - * @author Martin Odersky - */ -class CharSequenceReader(override val source: java.lang.CharSequence, - override val offset: Int) extends Reader[Char] { - import CharSequenceReader._ - - /** Construct a `CharSequenceReader` with its first element at - * `source(0)` and position `(1,1)`. - */ - def this(source: java.lang.CharSequence) = this(source, 0) - - /** Returns the first element of the reader, or EofCh if reader is at its end. - */ - def first = - if (offset < source.length) source.charAt(offset) else EofCh - - /** Returns a CharSequenceReader consisting of all elements except the first. - * - * @return If `atEnd` is `true`, the result will be `this`; - * otherwise, it's a `CharSequenceReader` containing the rest of input. - */ - def rest: CharSequenceReader = - if (offset < source.length) new CharSequenceReader(source, offset + 1) - else this - - /** The position of the first element in the reader. - */ - def pos: Position = new OffsetPosition(source, offset) - - /** true iff there are no more elements in this reader (except for trailing - * EofCh's) - */ - def atEnd = offset >= source.length - - /** Returns an abstract reader consisting of all elements except the first - * `n` elements. - */ - override def drop(n: Int): CharSequenceReader = - new CharSequenceReader(source, offset + n) -} diff --git a/src/library/scala/util/parsing/input/NoPosition.scala b/src/library/scala/util/parsing/input/NoPosition.scala deleted file mode 100644 index 40584b3293..0000000000 --- a/src/library/scala/util/parsing/input/NoPosition.scala +++ /dev/null @@ -1,24 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2006-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - - -package scala.util.parsing.input - -/** Undefined position. - * - * @author Martin Odersky - * @author Adriaan Moors - */ -object NoPosition extends Position { - def line = 0 - def column = 0 - override def toString = "<undefined position>" - override def longString = toString - def lineContents = "" -} diff --git a/src/library/scala/util/parsing/input/OffsetPosition.scala b/src/library/scala/util/parsing/input/OffsetPosition.scala deleted file mode 100644 index 01d9ea5cb8..0000000000 --- a/src/library/scala/util/parsing/input/OffsetPosition.scala +++ /dev/null @@ -1,72 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2006-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala.util.parsing.input - -import scala.collection.mutable.ArrayBuffer - -/** `OffsetPosition` is a standard class for positions - * represented as offsets into a source ``document''. - * - * @param source The source document - * @param offset The offset indicating the position - * - * @author Martin Odersky - */ -case class OffsetPosition(source: java.lang.CharSequence, offset: Int) extends Position { - - /** An index that contains all line starts, including first line, and eof. */ - private lazy val index: Array[Int] = { - var lineStarts = new ArrayBuffer[Int] - lineStarts += 0 - for (i <- 0 until source.length) - if (source.charAt(i) == '\n') lineStarts += (i + 1) - lineStarts += source.length - lineStarts.toArray - } - - /** The line number referred to by the position; line numbers start at 1. */ - def line: Int = { - var lo = 0 - var hi = index.length - 1 - while (lo + 1 < hi) { - val mid = (hi + lo) / 2 - if (offset < index(mid)) hi = mid - else lo = mid - } - lo + 1 - } - - /** The column number referred to by the position; column numbers start at 1. */ - def column: Int = offset - index(line - 1) + 1 - - /** The contents of the line numbered at the current offset. - * - * @return the line at `offset` (not including a newline) - */ - def lineContents: String = - source.subSequence(index(line - 1), index(line)).toString - - /** Returns a string representation of the `Position`, of the form `line.column`. */ - override def toString = line+"."+column - - /** Compare this position to another, by first comparing their line numbers, - * and then -- if necessary -- using the columns to break a tie. - * - * @param that a `Position` to compare to this `Position` - * @return true if this position's line number or (in case of equal line numbers) - * column is smaller than the corresponding components of `that` - */ - override def <(that: Position) = that match { - case OffsetPosition(_, that_offset) => - this.offset < that_offset - case _ => - this.line < that.line || - this.line == that.line && this.column < that.column - } -} diff --git a/src/library/scala/util/parsing/input/PagedSeqReader.scala b/src/library/scala/util/parsing/input/PagedSeqReader.scala deleted file mode 100644 index 9140bf2a4f..0000000000 --- a/src/library/scala/util/parsing/input/PagedSeqReader.scala +++ /dev/null @@ -1,70 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2006-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - -package scala.util.parsing.input - -import scala.collection.immutable.PagedSeq - -/** An object encapsulating basic character constants. - * - * @author Martin Odersky - * @author Adriaan Moors - */ -object PagedSeqReader { - final val EofCh = '\032' -} - -/** A character array reader reads a stream of characters (keeping track of their positions) - * from an array. - * - * @param seq the source sequence - * @param offset starting offset. - * - * @author Martin Odersky - */ -class PagedSeqReader(seq: PagedSeq[Char], - override val offset: Int) extends Reader[Char] { - import PagedSeqReader._ - - override lazy val source: java.lang.CharSequence = seq - - /** Construct a `PagedSeqReader` with its first element at - * `source(0)` and position `(1,1)`. - */ - def this(seq: PagedSeq[Char]) = this(seq, 0) - - /** Returns the first element of the reader, or EofCh if reader is at its end - */ - def first = - if (seq.isDefinedAt(offset)) seq(offset) else EofCh - - /** Returns a PagedSeqReader consisting of all elements except the first - * - * @return If `atEnd` is `true`, the result will be `this`; - * otherwise, it's a `PagedSeqReader` containing the rest of input. - */ - def rest: PagedSeqReader = - if (seq.isDefinedAt(offset)) new PagedSeqReader(seq, offset + 1) - else this - - /** The position of the first element in the reader. - */ - def pos: Position = new OffsetPosition(source, offset) - - /** true iff there are no more elements in this reader (except for trailing - * EofCh's). - */ - def atEnd = !seq.isDefinedAt(offset) - - /** Returns an abstract reader consisting of all elements except the first - * `n` elements. - */ - override def drop(n: Int): PagedSeqReader = - new PagedSeqReader(seq, offset + n) -} diff --git a/src/library/scala/util/parsing/input/Position.scala b/src/library/scala/util/parsing/input/Position.scala deleted file mode 100644 index 31715bd8da..0000000000 --- a/src/library/scala/util/parsing/input/Position.scala +++ /dev/null @@ -1,61 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2006-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala.util.parsing.input - -/** `Position` is the base trait for objects describing a position in a ``document''. - * - * It provides functionality for: - * - generating a visual representation of this position (`longString`); - * - comparing two positions (`<`). - * - * To use this class for a concrete kind of ``document'', implement the `lineContents` method. - * - * @author Martin Odersky - * @author Adriaan Moors - */ -trait Position { - - /** The line number referred to by the position; line numbers start at 1. */ - def line: Int - - /** The column number referred to by the position; column numbers start at 1. */ - def column: Int - - /** The contents of the line at this position. (must not contain a new-line character). - */ - protected def lineContents: String - - /** Returns a string representation of the `Position`, of the form `line.column`. */ - override def toString = ""+line+"."+column - - /** Returns a more ``visual'' representation of this position. - * More precisely, the resulting string consists of two lines: - * 1. the line in the document referred to by this position - * 2. a caret indicating the column - * - * Example: - * {{{ - * List(this, is, a, line, from, the, document) - * ^ - * }}} - */ - def longString = lineContents+"\n"+lineContents.take(column-1).map{x => if (x == '\t') x else ' ' } + "^" - - /** Compare this position to another, by first comparing their line numbers, - * and then -- if necessary -- using the columns to break a tie. - * - * @param `that` a `Position` to compare to this `Position` - * @return true if this position's line number or (in case of equal line numbers) - * column is smaller than the corresponding components of `that` - */ - def <(that: Position) = { - this.line < that.line || - this.line == that.line && this.column < that.column - } -} diff --git a/src/library/scala/util/parsing/input/Positional.scala b/src/library/scala/util/parsing/input/Positional.scala deleted file mode 100644 index 87cb16eac5..0000000000 --- a/src/library/scala/util/parsing/input/Positional.scala +++ /dev/null @@ -1,29 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2006-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala.util.parsing.input - -/** A trait for objects that have a source position. - * - * @author Martin Odersky, Adriaan Moors - */ -trait Positional { - - /** The source position of this object, initially set to undefined. */ - var pos: Position = NoPosition - - /** If current source position is undefined, update it with given position `newpos` - * @return the object itself - */ - def setPos(newpos: Position): this.type = { - if (pos eq NoPosition) pos = newpos - this - } -} - - diff --git a/src/library/scala/util/parsing/input/Reader.scala b/src/library/scala/util/parsing/input/Reader.scala deleted file mode 100644 index bded57bee1..0000000000 --- a/src/library/scala/util/parsing/input/Reader.scala +++ /dev/null @@ -1,61 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2006-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - - -package scala.util.parsing.input - - -/** An interface for streams of values that have positions. - * - * @author Martin Odersky - * @author Adriaan Moors - */ -abstract class Reader[+T] { - - /** If this is a reader over character sequences, the underlying char sequence. - * If not, throws a `NoSuchMethodError` exception. - * - * @throws [[java.lang.NoSuchMethodError]] if this not a char sequence reader. - */ - def source: java.lang.CharSequence = - throw new NoSuchMethodError("not a char sequence reader") - - def offset: Int = - throw new NoSuchMethodError("not a char sequence reader") - - /** Returns the first element of the reader - */ - def first: T - - /** Returns an abstract reader consisting of all elements except the first - * - * @return If `atEnd` is `true`, the result will be `this'; - * otherwise, it's a `Reader` containing more elements. - */ - def rest: Reader[T] - - /** Returns an abstract reader consisting of all elements except the first `n` elements. - */ - def drop(n: Int): Reader[T] = { - var r: Reader[T] = this - var cnt = n - while (cnt > 0) { - r = r.rest; cnt -= 1 - } - r - } - - /** The position of the first element in the reader. - */ - def pos: Position - - /** `true` iff there are no more elements in this reader. - */ - def atEnd: Boolean -} diff --git a/src/library/scala/util/parsing/input/StreamReader.scala b/src/library/scala/util/parsing/input/StreamReader.scala deleted file mode 100644 index ba7ab65845..0000000000 --- a/src/library/scala/util/parsing/input/StreamReader.scala +++ /dev/null @@ -1,75 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2006-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala.util.parsing.input - -import java.io.BufferedReader -import scala.collection.immutable.PagedSeq - -/** An object to create a `StreamReader` from a `java.io.Reader`. - * - * @author Miles Sabin - */ -object StreamReader { - final val EofCh = '\032' - - /** Create a `StreamReader` from a `java.io.Reader`. - * - * @param in the `java.io.Reader` that provides the underlying - * stream of characters for this Reader. - */ - def apply(in: java.io.Reader): StreamReader = { - new StreamReader(PagedSeq.fromReader(in), 0, 1) - } -} - -/** A StreamReader reads from a character sequence, typically created as a PagedSeq - * from a java.io.Reader - * - * NOTE: - * StreamReaders do not really fulfill the new contract for readers, which - * requires a `source` CharSequence representing the full input. - * Instead source is treated line by line. - * As a consequence, regex matching cannot extend beyond a single line - * when a StreamReader are used for input. - * - * If you need to match regexes spanning several lines you should consider - * class `PagedSeqReader` instead. - * - * @author Miles Sabin - * @author Martin Odersky - */ -sealed class StreamReader(seq: PagedSeq[Char], off: Int, lnum: Int) extends PagedSeqReader(seq, off) { - import StreamReader._ - - override def rest: StreamReader = - if (off == seq.length) this - else if (seq(off) == '\n') - new StreamReader(seq.slice(off + 1), 0, lnum + 1) - else new StreamReader(seq, off + 1, lnum) - - private def nextEol = { - var i = off - while (i < seq.length && seq(i) != '\n' && seq(i) != EofCh) i += 1 - i - } - - override def drop(n: Int): StreamReader = { - val eolPos = nextEol - if (eolPos < off + n && eolPos < seq.length) - new StreamReader(seq.slice(eolPos + 1), 0, lnum + 1).drop(off + n - (eolPos + 1)) - else - new StreamReader(seq, off + n, lnum) - } - - override def pos: Position = new Position { - def line = lnum - def column = off + 1 - def lineContents = seq.slice(0, nextEol).toString - } -} diff --git a/src/library/scala/util/parsing/json/JSON.scala b/src/library/scala/util/parsing/json/JSON.scala deleted file mode 100644 index 2f450ed864..0000000000 --- a/src/library/scala/util/parsing/json/JSON.scala +++ /dev/null @@ -1,98 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2006-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala.util.parsing.json -import scala.util.parsing.combinator._ -import scala.util.parsing.combinator.syntactical._ -import scala.util.parsing.combinator.lexical._ - -/** - * This object provides a simple interface to the JSON parser class. - * The default conversion for numerics is into a double. If you wish to - * override this behavior at the global level, you can set the - * `globalNumberParser` property to your own `(String => Any)` function. - * If you only want to override at the per-thread level then you can set - * the `perThreadNumberParser` property to your function. For example: - * {{{ - * val myConversionFunc = {input : String => BigDecimal(input)} - * - * // Global override - * JSON.globalNumberParser = myConversionFunc - * - * // Per-thread override - * JSON.perThreadNumberParser = myConversionFunc - * }}} - * - * @author Derek Chen-Becker <"java"+@+"chen-becker"+"."+"org"> - */ -object JSON extends Parser { - - /** - * This method converts ''raw'' results back into the original, deprecated - * form. - */ - private def unRaw (in : Any) : Any = in match { - case JSONObject(obj) => obj.map({ case (k,v) => (k,unRaw(v))}).toList - case JSONArray(list) => list.map(unRaw) - case x => x - } - - /** - * Parse the given `JSON` string and return a list of elements. If the - * string is a `JSON` object it will be a `JSONObject`. If it's a `JSON` - * array it will be a `JSONArray`. - * - * @param input the given `JSON` string. - * @return an optional `JSONType` element. - */ - def parseRaw(input : String) : Option[JSONType] = - phrase(root)(new lexical.Scanner(input)) match { - case Success(result, _) => Some(result) - case _ => None - } - - /** - * Parse the given `JSON` string and return either a `List[Any]` - * if the `JSON` string specifies an `Array`, or a - * `Map[String,Any]` if the `JSON` string specifies an object. - * - * @param input the given `JSON` string. - * @return an optional list or map. - */ - def parseFull(input: String): Option[Any] = - parseRaw(input) match { - case Some(data) => Some(resolveType(data)) - case None => None - } - - /** - * A utility method to resolve a parsed `JSON` list into objects or - * arrays. See the `parse` method for details. - */ - def resolveType(input: Any): Any = input match { - case JSONObject(data) => data.transform { - case (k,v) => resolveType(v) - } - case JSONArray(data) => data.map(resolveType) - case x => x - } - - /** - * The global (VM) default function for converting a string to a numeric value. - */ - def globalNumberParser_=(f: NumericParser) { defaultNumberParser = f } - def globalNumberParser : NumericParser = defaultNumberParser - - /** - * Defines the function used to convert a numeric string literal into a - * numeric format on a per-thread basis. Use `globalNumberParser` for a - * global override. - */ - def perThreadNumberParser_=(f : NumericParser) { numberParser.set(f) } - def perThreadNumberParser : NumericParser = numberParser.get() -} diff --git a/src/library/scala/util/parsing/json/Lexer.scala b/src/library/scala/util/parsing/json/Lexer.scala deleted file mode 100644 index 991b5d5c6c..0000000000 --- a/src/library/scala/util/parsing/json/Lexer.scala +++ /dev/null @@ -1,89 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2006-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - - -package scala.util.parsing.json - -import scala.util.parsing.combinator._ -import scala.util.parsing.combinator.syntactical._ -import scala.util.parsing.combinator.lexical._ -import scala.util.parsing.input.CharArrayReader.EofCh - -/** - * @author Derek Chen-Becker <"java"+@+"chen-becker"+"."+"org"> - */ -class Lexer extends StdLexical with ImplicitConversions { - - override def token: Parser[Token] = - //( '\"' ~ rep(charSeq | letter) ~ '\"' ^^ lift(StringLit) - ( string ^^ StringLit - | number ~ letter ^^ { case n ~ l => ErrorToken("Invalid number format : " + n + l) } - | '-' ~> whitespace ~ number ~ letter ^^ { case ws ~ num ~ l => ErrorToken("Invalid number format : -" + num + l) } - | '-' ~> whitespace ~ number ^^ { case ws ~ num => NumericLit("-" + num) } - | number ^^ NumericLit - | EofCh ^^^ EOF - | delim - | '\"' ~> failure("Unterminated string") - | rep(letter) ^^ checkKeyword - | failure("Illegal character") - ) - - def checkKeyword(xs : List[Any]) = { - val strRep = xs mkString "" - if (reserved contains strRep) Keyword(strRep) else ErrorToken("Not a keyword: " + strRep) - } - - /** A string is a collection of zero or more Unicode characters, wrapped in - * double quotes, using backslash escapes (cf. http://www.json.org/). - */ - def string = '\"' ~> rep(charSeq | chrExcept('\"', '\n', EofCh)) <~ '\"' ^^ { _ mkString "" } - - override def whitespace = rep(whitespaceChar) - - def number = intPart ~ opt(fracPart) ~ opt(expPart) ^^ { case i ~ f ~ e => - i + optString(".", f) + optString("", e) - } - def intPart = zero | intList - def intList = nonzero ~ rep(digit) ^^ {case x ~ y => (x :: y) mkString ""} - def fracPart = '.' ~> rep(digit) ^^ { _ mkString "" } - def expPart = exponent ~ opt(sign) ~ rep1(digit) ^^ { case e ~ s ~ d => - e + optString("", s) + d.mkString("") - } - - private def optString[A](pre: String, a: Option[A]) = a match { - case Some(x) => pre + x.toString - case None => "" - } - - def zero: Parser[String] = '0' ^^^ "0" - def nonzero = elem("nonzero digit", d => d.isDigit && d != '0') - def exponent = elem("exponent character", d => d == 'e' || d == 'E') - def sign = elem("sign character", d => d == '-' || d == '+') - - def charSeq: Parser[String] = - ('\\' ~ '\"' ^^^ "\"" - |'\\' ~ '\\' ^^^ "\\" - |'\\' ~ '/' ^^^ "/" - |'\\' ~ 'b' ^^^ "\b" - |'\\' ~ 'f' ^^^ "\f" - |'\\' ~ 'n' ^^^ "\n" - |'\\' ~ 'r' ^^^ "\r" - |'\\' ~ 't' ^^^ "\t" - |'\\' ~> 'u' ~> unicodeBlock) - - val hexDigits = Set[Char]() ++ "0123456789abcdefABCDEF".toArray - def hexDigit = elem("hex digit", hexDigits.contains(_)) - - private def unicodeBlock = hexDigit ~ hexDigit ~ hexDigit ~ hexDigit ^^ { - case a ~ b ~ c ~ d => - new String(Array(Integer.parseInt(List(a, b, c, d) mkString "", 16)), 0, 1) - } - - //private def lift[T](f: String => T)(xs: List[Any]): T = f(xs mkString "") -} diff --git a/src/library/scala/util/parsing/json/Parser.scala b/src/library/scala/util/parsing/json/Parser.scala deleted file mode 100644 index cb87866f07..0000000000 --- a/src/library/scala/util/parsing/json/Parser.scala +++ /dev/null @@ -1,142 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2006-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - - -package scala.util.parsing.json - -import scala.util.parsing.combinator._ -import scala.util.parsing.combinator.syntactical._ -import scala.util.parsing.combinator.lexical._ - -/** - * A marker class for the JSON result types. - * - * @author Derek Chen-Becker <"java"+@+"chen-becker"+"."+"org"> - */ -sealed abstract class JSONType { - /** - * This version of toString allows you to provide your own value - * formatter. - */ - def toString (formatter : JSONFormat.ValueFormatter) : String - - /** - * Returns a String representation of this JSON value - * using the JSONFormat.defaultFormatter. - */ - override def toString = toString(JSONFormat.defaultFormatter) -} - -/** - * This object defines functions that are used when converting JSONType - * values into String representations. Mostly this is concerned with - * proper quoting of strings. - * - * @author Derek Chen-Becker <"java"+@+"chen-becker"+"."+"org"> - */ -object JSONFormat { - /** - * This type defines a function that can be used to - * format values into JSON format. - */ - type ValueFormatter = Any => String - - /** - * The default formatter used by the library. You can - * provide your own with the toString calls on - * JSONObject and JSONArray instances. - */ - val defaultFormatter : ValueFormatter = (x : Any) => x match { - case s : String => "\"" + quoteString(s) + "\"" - case jo : JSONObject => jo.toString(defaultFormatter) - case ja : JSONArray => ja.toString(defaultFormatter) - case other => other.toString - } - - /** - * This function can be used to properly quote Strings - * for JSON output. - */ - def quoteString (s : String) : String = - s.map { - case '"' => "\\\"" - case '\\' => "\\\\" - case '/' => "\\/" - case '\b' => "\\b" - case '\f' => "\\f" - case '\n' => "\\n" - case '\r' => "\\r" - case '\t' => "\\t" - /* We'll unicode escape any control characters. These include: - * 0x0 -> 0x1f : ASCII Control (C0 Control Codes) - * 0x7f : ASCII DELETE - * 0x80 -> 0x9f : C1 Control Codes - * - * Per RFC4627, section 2.5, we're not technically required to - * encode the C1 codes, but we do to be safe. - */ - case c if ((c >= '\u0000' && c <= '\u001f') || (c >= '\u007f' && c <= '\u009f')) => "\\u%04x".format(c: Int) - case c => c - }.mkString -} - -/** - * Represents a JSON Object (map). - * - * @author Derek Chen-Becker <"java"+@+"chen-becker"+"."+"org"> - */ -case class JSONObject (obj : Map[String,Any]) extends JSONType { - def toString (formatter : JSONFormat.ValueFormatter) = - "{" + obj.map({ case (k,v) => formatter(k.toString) + " : " + formatter(v) }).mkString(", ") + "}" -} - -/** - * Represents a JSON Array (list). - * @author Derek Chen-Becker <"java"+@+"chen-becker"+"."+"org"> - */ -case class JSONArray (list : List[Any]) extends JSONType { - def toString (formatter : JSONFormat.ValueFormatter) = - "[" + list.map(formatter).mkString(", ") + "]" -} - -/** - * The main JSON Parser. - * - * @author Derek Chen-Becker <"java"+@+"chen-becker"+"."+"org"> - */ -class Parser extends StdTokenParsers with ImplicitConversions { - // Fill in abstract defs - type Tokens = Lexer - val lexical = new Tokens - - // Configure lexical parsing - lexical.reserved ++= List("true", "false", "null") - lexical.delimiters ++= List("{", "}", "[", "]", ":", ",") - - /** Type signature for functions that can parse numeric literals */ - type NumericParser = String => Any - - // Global default number parsing function - protected var defaultNumberParser : NumericParser = {_.toDouble} - - // Per-thread default number parsing function - protected val numberParser = new ThreadLocal[NumericParser]() { - override def initialValue() = defaultNumberParser - } - - // Define the grammar - def root = jsonObj | jsonArray - def jsonObj = "{" ~> repsep(objEntry, ",") <~ "}" ^^ { case vals : List[_] => JSONObject(Map(vals : _*)) } - def jsonArray = "[" ~> repsep(value, ",") <~ "]" ^^ { case vals : List[_] => JSONArray(vals) } - def objEntry = stringVal ~ (":" ~> value) ^^ { case x ~ y => (x, y) } - def value: Parser[Any] = (jsonObj | jsonArray | number | "true" ^^^ true | "false" ^^^ false | "null" ^^^ null | stringVal) - def stringVal = accept("string", { case lexical.StringLit(n) => n} ) - def number = accept("number", { case lexical.NumericLit(n) => numberParser.get.apply(n)} ) -} - diff --git a/src/library/scala/util/regexp/Base.scala b/src/library/scala/util/regexp/Base.scala deleted file mode 100644 index 7dbe60a34e..0000000000 --- a/src/library/scala/util/regexp/Base.scala +++ /dev/null @@ -1,66 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - - -package scala.util.regexp - -/** Basic regular expressions. - * - * @author Burak Emir - * @version 1.0 - */ - -@deprecated("This class will be removed", "2.10.0") -abstract class Base { - type _regexpT <: RegExp - - abstract class RegExp { - val isNullable: Boolean - } - - object Alt { - /** `Alt( R,R,R* )`. */ - def apply(rs: _regexpT*) = - if (rs.size < 2) throw new SyntaxError("need at least 2 branches in Alt") - else new Alt(rs: _*) - // Can't enforce that statically without changing the interface - // def apply(r1: _regexpT, r2: _regexpT, rs: _regexpT*) = new Alt(Seq(r1, r2) ++ rs: _*) - def unapplySeq(x: Alt) = Some(x.rs) - } - - class Alt private (val rs: _regexpT*) extends RegExp { - final val isNullable = rs exists (_.isNullable) - } - - object Sequ { - /** Sequ( R,R* ) */ - def apply(rs: _regexpT*) = if (rs.isEmpty) Eps else new Sequ(rs: _*) - def unapplySeq(x: Sequ) = Some(x.rs) - } - - class Sequ private (val rs: _regexpT*) extends RegExp { - final val isNullable = rs forall (_.isNullable) - } - - case class Star(r: _regexpT) extends RegExp { - final lazy val isNullable = true - } - - // The empty Sequ. - case object Eps extends RegExp { - final lazy val isNullable = true - override def toString() = "Eps" - } - - /** this class can be used to add meta information to regexps. */ - class Meta(r1: _regexpT) extends RegExp { - final val isNullable = r1.isNullable - def r = r1 - } -} diff --git a/src/library/scala/util/regexp/PointedHedgeExp.scala b/src/library/scala/util/regexp/PointedHedgeExp.scala deleted file mode 100644 index 5c0379b6f8..0000000000 --- a/src/library/scala/util/regexp/PointedHedgeExp.scala +++ /dev/null @@ -1,36 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - - -package scala.util.regexp - -/** Pointed regular hedge expressions, a useful subclass of regular hedge expressions. - * - * @author Burak Emir - * @version 1.0 - */ -@deprecated("This class will be removed", "2.10.0") -abstract class PointedHedgeExp extends Base { - - type _regexpT <: RegExp - type _labelT - - case class Node(label: _labelT, r: _regexpT) extends RegExp { - final val isNullable = false - } - - case class TopIter(r1: _regexpT, r2: _regexpT) extends RegExp { - final val isNullable = r1.isNullable && r2.isNullable //? - } - - case object Point extends RegExp { - final val isNullable = false - } - -} diff --git a/src/library/scala/util/regexp/SyntaxError.scala b/src/library/scala/util/regexp/SyntaxError.scala deleted file mode 100644 index 1788fdfb84..0000000000 --- a/src/library/scala/util/regexp/SyntaxError.scala +++ /dev/null @@ -1,20 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - - -package scala.util.regexp - -/** This runtime exception is thrown if an attempt to instantiate a - * syntactically incorrect expression is detected. - * - * @author Burak Emir - * @version 1.0 - */ -@deprecated("This class will be removed", "2.10.0") -class SyntaxError(e: String) extends RuntimeException(e) diff --git a/src/library/scala/util/regexp/WordExp.scala b/src/library/scala/util/regexp/WordExp.scala deleted file mode 100644 index 3c0c2ec156..0000000000 --- a/src/library/scala/util/regexp/WordExp.scala +++ /dev/null @@ -1,58 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - - -package scala.util.regexp - -/** - * The class `WordExp` provides regular word expressions. - * - * Users have to instantiate type member `_regexpT <;: RegExp` - * (from class `Base`) and a type member `_labelT <;: Label`. - * - * Here is a short example: - * {{{ - * import scala.util.regexp._ - * import scala.util.automata._ - * object MyLang extends WordExp { - * type _regexpT = RegExp - * type _labelT = MyChar - * - * case class MyChar(c:Char) extends Label - * } - * import MyLang._ - * // (a* | b)* - * val rex = Star(Alt(Star(Letter(MyChar('a'))),Letter(MyChar('b')))) - * object MyBerriSethi extends WordBerrySethi { - * override val lang = MyLang - * } - * val nfa = MyBerriSethi.automatonFrom(Sequ(rex), 1) - * }}} - * - * @author Burak Emir - * @version 1.0 - */ -@deprecated("This class will be removed", "2.10.0") -abstract class WordExp extends Base { - - abstract class Label - - type _regexpT <: RegExp - type _labelT <: Label - - case class Letter(a: _labelT) extends RegExp { - final lazy val isNullable = false - var pos = -1 - } - - case class Wildcard() extends RegExp { - final lazy val isNullable = false - var pos = -1 - } -} diff --git a/src/library/scala/volatile.scala b/src/library/scala/volatile.scala index bea216eb17..c612732329 100644 --- a/src/library/scala/volatile.scala +++ b/src/library/scala/volatile.scala @@ -6,8 +6,6 @@ ** |/ ** \* */ - - package scala import scala.annotation.meta._ diff --git a/src/library/scala/xml/Atom.scala b/src/library/scala/xml/Atom.scala deleted file mode 100644 index cba0b96875..0000000000 --- a/src/library/scala/xml/Atom.scala +++ /dev/null @@ -1,46 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala.xml - -/** The class `Atom` provides an XML node for text (`PCDATA`). - * It is used in both non-bound and bound XML representations. - * - * @author Burak Emir - * @param data the text contained in this node, may not be `'''null'''`. - */ -class Atom[+A](val data: A) extends SpecialNode with Serializable { - if (data == null) - throw new IllegalArgumentException("cannot construct "+getClass.getSimpleName+" with null") - - override protected def basisForHashCode: Seq[Any] = Seq(data) - - override def strict_==(other: Equality) = other match { - case x: Atom[_] => data == x.data - case _ => false - } - - override def canEqual(other: Any) = other match { - case _: Atom[_] => true - case _ => false - } - - final override def doCollectNamespaces = false - final override def doTransform = false - - def label = "#PCDATA" - - /** Returns text, with some characters escaped according to the XML - * specification. - */ - def buildString(sb: StringBuilder): StringBuilder = - Utility.escape(data.toString, sb) - - override def text: String = data.toString - -} diff --git a/src/library/scala/xml/Attribute.scala b/src/library/scala/xml/Attribute.scala deleted file mode 100644 index 0224913cf6..0000000000 --- a/src/library/scala/xml/Attribute.scala +++ /dev/null @@ -1,100 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala.xml - -/** This singleton object contains the `apply` and `unapply` methods for - * convenient construction and deconstruction. - * - * @author Burak Emir - * @version 1.0 - */ -object Attribute { - def unapply(x: Attribute) = x match { - case PrefixedAttribute(_, key, value, next) => Some((key, value, next)) - case UnprefixedAttribute(key, value, next) => Some((key, value, next)) - case _ => None - } - - /** Convenience functions which choose Un/Prefixedness appropriately */ - def apply(key: String, value: Seq[Node], next: MetaData): Attribute = - new UnprefixedAttribute(key, value, next) - - def apply(pre: String, key: String, value: String, next: MetaData): Attribute = - if (pre == null || pre == "") new UnprefixedAttribute(key, value, next) - else new PrefixedAttribute(pre, key, value, next) - - def apply(pre: String, key: String, value: Seq[Node], next: MetaData): Attribute = - if (pre == null || pre == "") new UnprefixedAttribute(key, value, next) - else new PrefixedAttribute(pre, key, value, next) - - def apply(pre: Option[String], key: String, value: Seq[Node], next: MetaData): Attribute = - pre match { - case None => new UnprefixedAttribute(key, value, next) - case Some(p) => new PrefixedAttribute(p, key, value, next) - } -} - -/** The `Attribute` trait defines the interface shared by both - * [[scala.xml.PrefixedAttribute]] and [[scala.xml.UnprefixedAttribute]]. - * - * @author Burak Emir - * @version 1.0 - */ -abstract trait Attribute extends MetaData { - def pre: String // will be null if unprefixed - val key: String - val value: Seq[Node] - val next: MetaData - - def apply(key: String): Seq[Node] - def apply(namespace: String, scope: NamespaceBinding, key: String): Seq[Node] - def copy(next: MetaData): Attribute - - def remove(key: String) = - if (!isPrefixed && this.key == key) next - else copy(next remove key) - - def remove(namespace: String, scope: NamespaceBinding, key: String) = - if (this.key == key && (scope getURI pre) == namespace) next - else copy(next.remove(namespace, scope, key)) - - def isPrefixed: Boolean = pre != null - - def getNamespace(owner: Node): String - - def wellformed(scope: NamespaceBinding): Boolean = { - val arg = if (isPrefixed) scope getURI pre else null - (next(arg, scope, key) == null) && (next wellformed scope) - } - - /** Returns an iterator on attributes */ - override def iterator: Iterator[MetaData] = { - if (value == null) next.iterator - else Iterator.single(this) ++ next.iterator - } - - override def size: Int = { - if (value == null) next.size - else 1 + next.size - } - - /** Appends string representation of only this attribute to stringbuffer. - */ - protected def toString1(sb: StringBuilder) { - if (value == null) - return - if (isPrefixed) - sb append pre append ':' - - sb append key append '=' - val sb2 = new StringBuilder() - Utility.sequenceToXML(value, TopScope, sb2, true) - Utility.appendQuoted(sb2.toString, sb) - } -} diff --git a/src/library/scala/xml/Comment.scala b/src/library/scala/xml/Comment.scala deleted file mode 100644 index ff4280d691..0000000000 --- a/src/library/scala/xml/Comment.scala +++ /dev/null @@ -1,30 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala.xml - -/** The class `Comment` implements an XML node for comments. - * - * @author Burak Emir - * @param commentText the text contained in this node, may not contain "--" - */ -case class Comment(commentText: String) extends SpecialNode { - - def label = "#REM" - override def text = "" - final override def doCollectNamespaces = false - final override def doTransform = false - - if (commentText contains "--") - throw new IllegalArgumentException("text contains \"--\"") - - /** Appends "<!-- text -->" to this string buffer. - */ - override def buildString(sb: StringBuilder) = - sb append "<!--" append commentText append "-->" -} diff --git a/src/library/scala/xml/Document.scala b/src/library/scala/xml/Document.scala deleted file mode 100644 index a064c4d8e8..0000000000 --- a/src/library/scala/xml/Document.scala +++ /dev/null @@ -1,91 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala.xml - -/** A document information item (according to InfoSet spec). The comments - * are copied from the Infoset spec, only augmented with some information - * on the Scala types for definitions that might have no value. - * Also plays the role of an `XMLEvent` for pull parsing. - * - * @author Burak Emir - * @version 1.0, 26/04/2005 - */ -@SerialVersionUID(-2289320563321795109L) -class Document extends NodeSeq with pull.XMLEvent with Serializable { - - /** An ordered list of child information items, in document - * order. The list contains exactly one element information item. The - * list also contains one processing instruction information item for - * each processing instruction outside the document element, and one - * comment information item for each comment outside the document - * element. Processing instructions and comments within the DTD are - * excluded. If there is a document type declaration, the list also - * contains a document type declaration information item. - */ - var children: Seq[Node] = _ - - /** The element information item corresponding to the document element. */ - var docElem: Node = _ - - /** The dtd that comes with the document, if any */ - var dtd: scala.xml.dtd.DTD = _ - - /** An unordered set of notation information items, one for each notation - * declared in the DTD. If any notation is multiply declared, this property - * has no value. - */ - def notations: Seq[scala.xml.dtd.NotationDecl] = - dtd.notations - - /** An unordered set of unparsed entity information items, one for each - * unparsed entity declared in the DTD. - */ - def unparsedEntities: Seq[scala.xml.dtd.EntityDecl] = - dtd.unparsedEntities - - /** The base URI of the document entity. */ - var baseURI: String = _ - - /** The name of the character encoding scheme in which the document entity - * is expressed. - */ - var encoding: Option[String] = _ - - /** An indication of the standalone status of the document, either - * true or false. This property is derived from the optional standalone - * document declaration in the XML declaration at the beginning of the - * document entity, and has no value (`None`) if there is no - * standalone document declaration. - */ - var standAlone: Option[Boolean] = _ - - /** A string representing the XML version of the document. This - * property is derived from the XML declaration optionally present at - * the beginning of the document entity, and has no value (`None`) - * if there is no XML declaration. - */ - var version: Option[String] = _ - - /** 9. This property is not strictly speaking part of the infoset of - * the document. Rather it is an indication of whether the processor - * has read the complete DTD. Its value is a boolean. If it is false, - * then certain properties (indicated in their descriptions below) may - * be unknown. If it is true, those properties are never unknown. - */ - var allDeclarationsProcessed = false - - // methods for NodeSeq - - def theSeq: Seq[Node] = this.docElem - - override def canEqual(other: Any) = other match { - case _: Document => true - case _ => false - } -} diff --git a/src/library/scala/xml/Elem.scala b/src/library/scala/xml/Elem.scala deleted file mode 100755 index b9e665e292..0000000000 --- a/src/library/scala/xml/Elem.scala +++ /dev/null @@ -1,111 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala.xml - -/** This singleton object contains the `apply` and `unapplySeq` methods for - * convenient construction and deconstruction. It is possible to deconstruct - * any `Node` instance (that is not a `SpecialNode` or a `Group`) using the - * syntax `case Elem(prefix, label, attribs, scope, child @ _*) => ...` - * - * Copyright 2008 Google Inc. All Rights Reserved. - * @author Burak Emir <bqe@google.com> - */ -object Elem { - /** Build an Elem, setting its minimizeEmpty property to <code>true</code> if it has no children. Note that this - * default may not be exactly what you want, as some XML dialects don't permit some elements to be minimized. - * - * @deprecated This factory method is retained for backward compatibility; please use the other one, with which you - * can specify your own preference for minimizeEmpty. - */ - @deprecated("Use the other apply method in this object", "2.10.0") - def apply(prefix: String, label: String, attributes: MetaData, scope: NamespaceBinding, child: Node*): Elem = - apply(prefix, label, attributes, scope, child.isEmpty, child: _*) - - def apply(prefix: String, label: String, attributes: MetaData, scope: NamespaceBinding, minimizeEmpty: Boolean, child: Node*): Elem = - new Elem(prefix, label, attributes, scope, minimizeEmpty, child: _*) - - def unapplySeq(n: Node) = n match { - case _: SpecialNode | _: Group => None - case _ => Some((n.prefix, n.label, n.attributes, n.scope, n.child)) - } -} - -/** The case class `Elem` extends the `Node` class, - * providing an immutable data object representing an XML element. - * - * @param prefix namespace prefix (may be null, but not the empty string) - * @param label the element name - * @param attributes1 the attribute map - * @param scope the scope containing the namespace bindings - * @param minimizeEmpty `true` if this element should be serialized as minimized (i.e. "<el/>") when - * empty; `false` if it should be written out in long form. - * @param child the children of this node - * - * Copyright 2008 Google Inc. All Rights Reserved. - * @author Burak Emir <bqe@google.com> - */ -class Elem( - override val prefix: String, - val label: String, - attributes1: MetaData, - override val scope: NamespaceBinding, - val minimizeEmpty: Boolean, - val child: Node*) -extends Node with Serializable -{ - @deprecated("This constructor is retained for backward compatibility. Please use the primary constructor, which lets you specify your own preference for `minimizeEmpty`.", "2.10.0") - def this(prefix: String, label: String, attributes: MetaData, scope: NamespaceBinding, child: Node*) = { - this(prefix, label, attributes, scope, child.isEmpty, child: _*) - } - - final override def doCollectNamespaces = true - final override def doTransform = true - - override val attributes = MetaData.normalize(attributes1, scope) - - if (prefix == "") - throw new IllegalArgumentException("prefix of zero length, use null instead") - - if (scope == null) - throw new IllegalArgumentException("scope is null, use scala.xml.TopScope for empty scope") - - //@todo: copy the children, - // setting namespace scope if necessary - // cleaning adjacent text nodes if necessary - - override protected def basisForHashCode: Seq[Any] = - prefix :: label :: attributes :: child.toList - - /** Returns a new element with updated attributes, resolving namespace uris - * from this element's scope. See MetaData.update for details. - * - * @param updates MetaData with new and updated attributes - * @return a new symbol with updated attributes - */ - final def %(updates: MetaData): Elem = - copy(attributes = MetaData.update(attributes, scope, updates)) - - /** Returns a copy of this element with any supplied arguments replacing - * this element's value for that field. - * - * @return a new symbol with updated attributes - */ - def copy( - prefix: String = this.prefix, - label: String = this.label, - attributes: MetaData = this.attributes, - scope: NamespaceBinding = this.scope, - minimizeEmpty: Boolean = this.minimizeEmpty, - child: Seq[Node] = this.child.toSeq - ): Elem = Elem(prefix, label, attributes, scope, minimizeEmpty, child: _*) - - /** Returns concatenation of `text(n)` for each child `n`. - */ - override def text = (child map (_.text)).mkString -} diff --git a/src/library/scala/xml/EntityRef.scala b/src/library/scala/xml/EntityRef.scala deleted file mode 100644 index a7b9835a7e..0000000000 --- a/src/library/scala/xml/EntityRef.scala +++ /dev/null @@ -1,39 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala.xml - -/** The class `EntityRef` implements an XML node for entity references. - * - * @author Burak Emir - * @version 1.0 - * @param entityName the name of the entity reference, for example `amp`. - */ -case class EntityRef(entityName: String) extends SpecialNode { - final override def doCollectNamespaces = false - final override def doTransform = false - def label = "#ENTITY" - - override def text = entityName match { - case "lt" => "<" - case "gt" => ">" - case "amp" => "&" - case "apos" => "'" - case "quot" => "\"" - case _ => Utility.sbToString(buildString) - } - - /** Appends `"& entityName;"` to this string buffer. - * - * @param sb the string buffer. - * @return the modified string buffer `sb`. - */ - override def buildString(sb: StringBuilder) = - sb.append("&").append(entityName).append(";") - -} diff --git a/src/library/scala/xml/Equality.scala b/src/library/scala/xml/Equality.scala deleted file mode 100644 index 02db22a78a..0000000000 --- a/src/library/scala/xml/Equality.scala +++ /dev/null @@ -1,106 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala.xml - -/** In an attempt to contain the damage being inflicted on consistency by the - * ad hoc `equals` methods spread around `xml`, the logic is centralized and - * all the `xml` classes go through the `xml.Equality trait`. There are two - * forms of `xml` comparison. - * - * 1. `'''def''' strict_==(other: scala.xml.Equality)` - * - * This one tries to honor the little things like symmetry and hashCode - * contracts. The `equals` method routes all comparisons through this. - * - * 1. `xml_==(other: Any)` - * - * This one picks up where `strict_==` leaves off. It might declare any two - * things equal. - * - * As things stood, the logic not only made a mockery of the collections - * equals contract, but also laid waste to that of case classes. - * - * Among the obstacles to sanity are/were: - * - * Node extends NodeSeq extends Seq[Node] - * MetaData extends Iterable[MetaData] - * The hacky "Group" xml node which throws exceptions - * with wild abandon, so don't get too close - * Rampant asymmetry and impossible hashCodes - * Most classes claiming to be equal to "String" if - * some specific stringification of it was the same. - * String was never going to return the favor. - */ - -object Equality { - def asRef(x: Any): AnyRef = x.asInstanceOf[AnyRef] - - /** Note - these functions assume strict equality has already failed. - */ - def compareBlithely(x1: AnyRef, x2: String): Boolean = x1 match { - case x: Atom[_] => x.data == x2 - case x: NodeSeq => x.text == x2 - case _ => false - } - def compareBlithely(x1: AnyRef, x2: Node): Boolean = x1 match { - case x: NodeSeq if x.length == 1 => x2 == x(0) - case _ => false - } - def compareBlithely(x1: AnyRef, x2: AnyRef): Boolean = { - if (x1 == null || x2 == null) - return (x1 eq x2) - - x2 match { - case s: String => compareBlithely(x1, s) - case n: Node => compareBlithely(x1, n) - case _ => false - } - } -} -import Equality._ - -trait Equality extends scala.Equals { - protected def basisForHashCode: Seq[Any] - - def strict_==(other: Equality): Boolean - def strict_!=(other: Equality) = !strict_==(other) - - /** We insist we're only equal to other `xml.Equality` implementors, - * which heads off a lot of inconsistency up front. - */ - override def canEqual(other: Any): Boolean = other match { - case x: Equality => true - case _ => false - } - - /** It's be nice to make these final, but there are probably - * people out there subclassing the XML types, especially when - * it comes to equals. However WE at least can pretend they - * are final since clearly individual classes cannot be trusted - * to maintain a semblance of order. - */ - override def hashCode() = basisForHashCode.## - override def equals(other: Any) = doComparison(other, false) - final def xml_==(other: Any) = doComparison(other, true) - final def xml_!=(other: Any) = !xml_==(other) - - /** The "blithe" parameter expresses the caller's unconcerned attitude - * regarding the usual constraints on equals. The method is thereby - * given carte blanche to declare any two things equal. - */ - private def doComparison(other: Any, blithe: Boolean) = { - val strictlyEqual = other match { - case x: AnyRef if this eq x => true - case x: Equality => (x canEqual this) && (this strict_== x) - case _ => false - } - - strictlyEqual || (blithe && compareBlithely(this, asRef(other))) - } -} diff --git a/src/library/scala/xml/Group.scala b/src/library/scala/xml/Group.scala deleted file mode 100644 index 92da2f993f..0000000000 --- a/src/library/scala/xml/Group.scala +++ /dev/null @@ -1,41 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala.xml - -/** A hack to group XML nodes in one node for output. - * - * @author Burak Emir - * @version 1.0 - */ -final case class Group(val nodes: Seq[Node]) extends Node { - override def theSeq = nodes - - override def canEqual(other: Any) = other match { - case x: Group => true - case _ => false - } - - override def strict_==(other: Equality) = other match { - case Group(xs) => nodes sameElements xs - case _ => false - } - - override protected def basisForHashCode = nodes - - /** Since Group is very much a hack it throws an exception if you - * try to do anything with it. - */ - private def fail(msg: String) = throw new UnsupportedOperationException("class Group does not support method '%s'" format msg) - - def label = fail("label") - override def attributes = fail("attributes") - override def namespace = fail("namespace") - override def child = fail("child") - def buildString(sb: StringBuilder) = fail("toString(StringBuilder)") -} diff --git a/src/library/scala/xml/MalformedAttributeException.scala b/src/library/scala/xml/MalformedAttributeException.scala deleted file mode 100644 index 3431cb6765..0000000000 --- a/src/library/scala/xml/MalformedAttributeException.scala +++ /dev/null @@ -1,14 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - - -package scala.xml - - -case class MalformedAttributeException(msg: String) extends RuntimeException(msg) diff --git a/src/library/scala/xml/MetaData.scala b/src/library/scala/xml/MetaData.scala deleted file mode 100644 index 3bf3ebb1c0..0000000000 --- a/src/library/scala/xml/MetaData.scala +++ /dev/null @@ -1,216 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala.xml - -import Utility.sbToString -import scala.annotation.tailrec -import scala.collection.{ AbstractIterable, Iterator } - -/** - * Copyright 2008 Google Inc. All Rights Reserved. - * @author Burak Emir <bqe@google.com> - */ -object MetaData { - /** - * appends all attributes from new_tail to attribs, without attempting to - * detect or remove duplicates. The method guarantees that all attributes - * from attribs come before the attributes in new_tail, but does not - * guarantee to preserve the relative order of attribs. - * - * Duplicates can be removed with `normalize`. - */ - @tailrec // temporarily marked final so it will compile under -Xexperimental - final def concatenate(attribs: MetaData, new_tail: MetaData): MetaData = - if (attribs eq Null) new_tail - else concatenate(attribs.next, attribs copy new_tail) - - /** - * returns normalized MetaData, with all duplicates removed and namespace prefixes resolved to - * namespace URIs via the given scope. - */ - def normalize(attribs: MetaData, scope: NamespaceBinding): MetaData = { - def iterate(md: MetaData, normalized_attribs: MetaData, set: Set[String]): MetaData = { - lazy val key = getUniversalKey(md, scope) - if (md eq Null) normalized_attribs - else if ((md.value eq null) || set(key)) iterate(md.next, normalized_attribs, set) - else md copy iterate(md.next, normalized_attribs, set + key) - } - iterate(attribs, Null, Set()) - } - - /** - * returns key if md is unprefixed, pre+key is md is prefixed - */ - def getUniversalKey(attrib: MetaData, scope: NamespaceBinding) = attrib match { - case prefixed: PrefixedAttribute => scope.getURI(prefixed.pre) + prefixed.key - case unprefixed: UnprefixedAttribute => unprefixed.key - } - - /** - * returns MetaData with attributes updated from given MetaData - */ - def update(attribs: MetaData, scope: NamespaceBinding, updates: MetaData): MetaData = - normalize(concatenate(updates, attribs), scope) - -} - -/** This class represents an attribute and at the same time a linked list of - * attributes. Every instance of this class is either - * - an instance of `UnprefixedAttribute key,value` or - * - an instance of `PrefixedAttribute namespace_prefix,key,value` or - * - `Null, the empty attribute list. - * - * Namespace URIs are obtained by using the namespace scope of the element - * owning this attribute (see `getNamespace`). - * - * Copyright 2008 Google Inc. All Rights Reserved. - * @author Burak Emir <bqe@google.com> - */ -abstract class MetaData -extends AbstractIterable[MetaData] - with Iterable[MetaData] - with Equality - with Serializable { - - /** Updates this MetaData with the MetaData given as argument. All attributes that occur in updates - * are part of the resulting MetaData. If an attribute occurs in both this instance and - * updates, only the one in updates is part of the result (avoiding duplicates). For prefixed - * attributes, namespaces are resolved using the given scope, which defaults to TopScope. - * - * @param updates MetaData with new and updated attributes - * @return a new MetaData instance that contains old, new and updated attributes - */ - def append(updates: MetaData, scope: NamespaceBinding = TopScope): MetaData = - MetaData.update(this, scope, updates) - - /** - * Gets value of unqualified (unprefixed) attribute with given key, null if not found - * - * @param key - * @return value as Seq[Node] if key is found, null otherwise - */ - def apply(key: String): Seq[Node] - - /** convenience method, same as `apply(namespace, owner.scope, key)`. - * - * @param namespace_uri namespace uri of key - * @param owner the element owning this attribute list - * @param key the attribute key - */ - final def apply(namespace_uri: String, owner: Node, key: String): Seq[Node] = - apply(namespace_uri, owner.scope, key) - - /** - * Gets value of prefixed attribute with given key and namespace, null if not found - * - * @param namespace_uri namespace uri of key - * @param scp a namespace scp (usually of the element owning this attribute list) - * @param k to be looked for - * @return value as Seq[Node] if key is found, null otherwise - */ - def apply(namespace_uri: String, scp: NamespaceBinding, k: String): Seq[Node] - - /** returns a copy of this MetaData item with next field set to argument. - */ - def copy(next: MetaData): MetaData - - /** if owner is the element of this metadata item, returns namespace */ - def getNamespace(owner: Node): String - - def hasNext = (Null != next) - - def length: Int = length(0) - - def length(i: Int): Int = next.length(i + 1) - - def isPrefixed: Boolean - - override def canEqual(other: Any) = other match { - case _: MetaData => true - case _ => false - } - override def strict_==(other: Equality) = other match { - case m: MetaData => this.asAttrMap == m.asAttrMap - case _ => false - } - protected def basisForHashCode: Seq[Any] = List(this.asAttrMap) - - /** filters this sequence of meta data */ - override def filter(f: MetaData => Boolean): MetaData = - if (f(this)) copy(next filter f) - else next filter f - - /** returns key of this MetaData item */ - def key: String - - /** returns value of this MetaData item */ - def value: Seq[Node] - - /** Returns a String containing "prefix:key" if the first key is - * prefixed, and "key" otherwise. - */ - def prefixedKey = this match { - case x: Attribute if x.isPrefixed => x.pre + ":" + key - case _ => key - } - - /** Returns a Map containing the attributes stored as key/value pairs. - */ - def asAttrMap: Map[String, String] = - (iterator map (x => (x.prefixedKey, x.value.text))).toMap - - /** returns Null or the next MetaData item */ - def next: MetaData - - /** - * Gets value of unqualified (unprefixed) attribute with given key, None if not found - * - * @param key - * @return value in Some(Seq[Node]) if key is found, None otherwise - */ - final def get(key: String): Option[Seq[Node]] = Option(apply(key)) - - /** same as get(uri, owner.scope, key) */ - final def get(uri: String, owner: Node, key: String): Option[Seq[Node]] = - get(uri, owner.scope, key) - - /** gets value of qualified (prefixed) attribute with given key. - * - * @param uri namespace of key - * @param scope a namespace scp (usually of the element owning this attribute list) - * @param key to be looked fore - * @return value as Some[Seq[Node]] if key is found, None otherwise - */ - final def get(uri: String, scope: NamespaceBinding, key: String): Option[Seq[Node]] = - Option(apply(uri, scope, key)) - - protected def toString1(): String = sbToString(toString1) - - // appends string representations of single attribute to StringBuilder - protected def toString1(sb: StringBuilder): Unit - - override def toString(): String = sbToString(buildString) - - def buildString(sb: StringBuilder): StringBuilder = { - sb append ' ' - toString1(sb) - next buildString sb - } - - /** - */ - def wellformed(scope: NamespaceBinding): Boolean - - def remove(key: String): MetaData - - def remove(namespace: String, scope: NamespaceBinding, key: String): MetaData - - final def remove(namespace: String, owner: Node, key: String): MetaData = - remove(namespace, owner.scope, key) -} diff --git a/src/library/scala/xml/NamespaceBinding.scala b/src/library/scala/xml/NamespaceBinding.scala deleted file mode 100644 index c7cd9e6b6c..0000000000 --- a/src/library/scala/xml/NamespaceBinding.scala +++ /dev/null @@ -1,64 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala.xml - -import Utility.sbToString - -/** The class `NamespaceBinding` represents namespace bindings - * and scopes. The binding for the default namespace is treated as a null - * prefix. the absent namespace is represented with the null uri. Neither - * prefix nor uri may be empty, which is not checked. - * - * @author Burak Emir - * @version 1.0 - */ -@SerialVersionUID(0 - 2518644165573446725L) -case class NamespaceBinding(prefix: String, uri: String, parent: NamespaceBinding) extends AnyRef with Equality -{ - if (prefix == "") - throw new IllegalArgumentException("zero length prefix not allowed") - - def getURI(_prefix: String): String = - if (prefix == _prefix) uri else parent getURI _prefix - - /** Returns some prefix that is mapped to the URI. - * - * @param _uri the input URI - * @return the prefix that is mapped to the input URI, or null - * if no prefix is mapped to the URI. - */ - def getPrefix(_uri: String): String = - if (_uri == uri) prefix else parent getPrefix _uri - - override def toString(): String = sbToString(buildString(_, TopScope)) - - override def canEqual(other: Any) = other match { - case _: NamespaceBinding => true - case _ => false - } - - override def strict_==(other: Equality) = other match { - case x: NamespaceBinding => (prefix == x.prefix) && (uri == x.uri) && (parent == x.parent) - case _ => false - } - - def basisForHashCode: Seq[Any] = List(prefix, uri, parent) - - def buildString(stop: NamespaceBinding): String = sbToString(buildString(_, stop)) - - def buildString(sb: StringBuilder, stop: NamespaceBinding) { - if (this eq stop) return // contains? - - val s = " xmlns%s=\"%s\"".format( - (if (prefix != null) ":" + prefix else ""), - (if (uri != null) uri else "") - ) - parent.buildString(sb append s, stop) // copy(ignore) - } -} diff --git a/src/library/scala/xml/Node.scala b/src/library/scala/xml/Node.scala deleted file mode 100755 index 6b6c962692..0000000000 --- a/src/library/scala/xml/Node.scala +++ /dev/null @@ -1,197 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala.xml - -/** This singleton object contains the `unapplySeq` method for - * convenient deconstruction. - * - * @author Burak Emir - * @version 1.0 - */ -object Node { - /** the constant empty attribute sequence */ - final def NoAttributes: MetaData = Null - - /** the empty namespace */ - val EmptyNamespace = "" - - def unapplySeq(n: Node) = Some((n.label, n.attributes, n.child)) -} - -/** - * An abstract class representing XML with nodes of a labelled tree. - * This class contains an implementation of a subset of XPath for navigation. - * - * @author Burak Emir and others - * @version 1.1 - */ -abstract class Node extends NodeSeq { - - /** prefix of this node */ - def prefix: String = null - - /** label of this node. I.e. "foo" for <foo/>) */ - def label: String - - /** used internally. Atom/Molecule = -1 PI = -2 Comment = -3 EntityRef = -5 - */ - def isAtom = this.isInstanceOf[Atom[_]] - - /** The logic formerly found in typeTag$, as best I could infer it. */ - def doCollectNamespaces = true // if (tag >= 0) DO collect namespaces - def doTransform = true // if (tag < 0) DO NOT transform - - /** - * method returning the namespace bindings of this node. by default, this - * is TopScope, which means there are no namespace bindings except the - * predefined one for "xml". - */ - def scope: NamespaceBinding = TopScope - - /** - * convenience, same as <code>getNamespace(this.prefix)</code> - */ - def namespace = getNamespace(this.prefix) - - /** - * Convenience method, same as `scope.getURI(pre)` but additionally - * checks if scope is `'''null'''`. - * - * @param pre the prefix whose namespace name we would like to obtain - * @return the namespace if <code>scope != null</code> and prefix was - * found, else <code>null</code> - */ - def getNamespace(pre: String): String = if (scope eq null) null else scope.getURI(pre) - - /** - * Convenience method, looks up an unprefixed attribute in attributes of this node. - * Same as `attributes.getValue(key)` - * - * @param key of queried attribute. - * @return value of <code>UnprefixedAttribute</code> with given key - * in attributes, if it exists, otherwise <code>null</code>. - */ - final def attribute(key: String): Option[Seq[Node]] = attributes.get(key) - - /** - * Convenience method, looks up a prefixed attribute in attributes of this node. - * Same as `attributes.getValue(uri, this, key)`- - * - * @param uri namespace of queried attribute (may not be null). - * @param key of queried attribute. - * @return value of `PrefixedAttribute` with given namespace - * and given key, otherwise `'''null'''`. - */ - final def attribute(uri: String, key: String): Option[Seq[Node]] = - attributes.get(uri, this, key) - - /** - * Returns attribute meaning all attributes of this node, prefixed and - * unprefixed, in no particular order. In class `Node`, this - * defaults to `Null` (the empty attribute list). - * - * @return all attributes of this node - */ - def attributes: MetaData = Null - - /** - * Returns child axis i.e. all children of this node. - * - * @return all children of this node - */ - def child: Seq[Node] - - /** Children which do not stringify to "" (needed for equality) - */ - def nonEmptyChildren: Seq[Node] = child filterNot (_.toString == "") - - /** - * Descendant axis (all descendants of this node, not including node itself) - * includes all text nodes, element nodes, comments and processing instructions. - */ - def descendant: List[Node] = - child.toList.flatMap { x => x::x.descendant } - - /** - * Descendant axis (all descendants of this node, including thisa node) - * includes all text nodes, element nodes, comments and processing instructions. - */ - def descendant_or_self: List[Node] = this :: descendant - - override def canEqual(other: Any) = other match { - case x: Group => false - case x: Node => true - case _ => false - } - - override protected def basisForHashCode: Seq[Any] = - prefix :: label :: attributes :: nonEmptyChildren.toList - - override def strict_==(other: Equality) = other match { - case _: Group => false - case x: Node => - (prefix == x.prefix) && - (label == x.label) && - (attributes == x.attributes) && - // (scope == x.scope) // note - original code didn't compare scopes so I left it as is. - (nonEmptyChildren sameElements x.nonEmptyChildren) - case _ => - false - } - - // implementations of NodeSeq methods - - /** - * returns a sequence consisting of only this node - */ - def theSeq: Seq[Node] = this :: Nil - - /** - * String representation of this node - * - * @param stripComments if true, strips comment nodes from result - */ - def buildString(stripComments: Boolean): String = - Utility.serialize(this, stripComments = stripComments).toString - - /** - * Same as `toString('''false''')`. - */ - override def toString(): String = buildString(false) - - /** - * Appends qualified name of this node to `StringBuilder`. - */ - def nameToString(sb: StringBuilder): StringBuilder = { - if (null != prefix) { - sb append prefix - sb append ':' - } - sb append label - } - - /** - * Returns a type symbol (e.g. DTD, XSD), default `'''null'''`. - */ - def xmlType(): TypeSymbol = null - - /** - * Returns a text representation of this node. Note that this is not equivalent to - * the XPath node-test called text(), it is rather an implementation of the - * XPath function string() - * Martin to Burak: to do: if you make this method abstract, the compiler will now - * complain if there's no implementation in a subclass. Is this what we want? Note that - * this would break doc/DocGenator and doc/ModelToXML, with an error message like: - * {{{ - * doc\DocGenerator.scala:1219: error: object creation impossible, since there is a deferred declaration of method text in class Node of type => String which is not implemented in a subclass - * new SpecialNode { - * ^ - * }}} */ - override def text: String = super.text -} diff --git a/src/library/scala/xml/NodeBuffer.scala b/src/library/scala/xml/NodeBuffer.scala deleted file mode 100644 index 2db4338fb2..0000000000 --- a/src/library/scala/xml/NodeBuffer.scala +++ /dev/null @@ -1,46 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala.xml - -/** - * This class acts as a Buffer for nodes. If it is used as a sequence of - * nodes `Seq[Node]`, it must be ensured that no updates occur after that - * point, because `scala.xml.Node` is assumed to be immutable. - * - * Despite this being a sequence, don't use it as key in a hashtable. - * Calling the hashcode function will result in a runtime error. - * - * @author Burak Emir - * @version 1.0 - */ -class NodeBuffer extends scala.collection.mutable.ArrayBuffer[Node] { - - /** - * Append given object to this buffer, returns reference on this - * `NodeBuffer` for convenience. Some rules apply: - * - If argument `o` is `'''null'''`, it is ignored. - * - If it is an `Iterator` or `Iterable`, its elements will be added. - * - If `o` is a node, it is added as it is. - * - If it is anything else, it gets wrapped in an [[scala.xml.Atom]]. - * - * @param o converts to an xml node and adds to this node buffer - * @return this nodebuffer - */ - def &+(o: Any): NodeBuffer = { - o match { - case null | _: Unit | Text("") => // ignore - case it: Iterator[_] => it foreach &+ - case n: Node => super.+=(n) - case ns: Iterable[_] => this &+ ns.iterator - case ns: Array[_] => this &+ ns.iterator - case d => super.+=(new Atom(d)) - } - this - } -} diff --git a/src/library/scala/xml/NodeSeq.scala b/src/library/scala/xml/NodeSeq.scala deleted file mode 100644 index decf60dad7..0000000000 --- a/src/library/scala/xml/NodeSeq.scala +++ /dev/null @@ -1,151 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala.xml - -import scala.collection.{ mutable, immutable, generic, SeqLike, AbstractSeq } -import mutable.{ Builder, ListBuffer } -import generic.{ CanBuildFrom } -import scala.language.implicitConversions - -/** This object ... - * - * @author Burak Emir - * @version 1.0 - */ -object NodeSeq { - final val Empty = fromSeq(Nil) - def fromSeq(s: Seq[Node]): NodeSeq = new NodeSeq { - def theSeq = s - } - type Coll = NodeSeq - implicit def canBuildFrom: CanBuildFrom[Coll, Node, NodeSeq] = - new CanBuildFrom[Coll, Node, NodeSeq] { - def apply(from: Coll) = newBuilder - def apply() = newBuilder - } - def newBuilder: Builder[Node, NodeSeq] = new ListBuffer[Node] mapResult fromSeq - implicit def seqToNodeSeq(s: Seq[Node]): NodeSeq = fromSeq(s) -} - -/** This class implements a wrapper around `Seq[Node]` that adds XPath - * and comprehension methods. - * - * @author Burak Emir - * @version 1.0 - */ -abstract class NodeSeq extends AbstractSeq[Node] with immutable.Seq[Node] with SeqLike[Node, NodeSeq] with Equality { - import NodeSeq.seqToNodeSeq // import view magic for NodeSeq wrappers - - /** Creates a list buffer as builder for this class */ - override protected[this] def newBuilder = NodeSeq.newBuilder - - def theSeq: Seq[Node] - def length = theSeq.length - override def iterator = theSeq.iterator - - def apply(i: Int): Node = theSeq(i) - def apply(f: Node => Boolean): NodeSeq = filter(f) - - def xml_sameElements[A](that: Iterable[A]): Boolean = { - val these = this.iterator - val those = that.iterator - while (these.hasNext && those.hasNext) - if (these.next xml_!= those.next) - return false - - !these.hasNext && !those.hasNext - } - - protected def basisForHashCode: Seq[Any] = theSeq - - override def canEqual(other: Any) = other match { - case _: NodeSeq => true - case _ => false - } - - override def strict_==(other: Equality) = other match { - case x: NodeSeq => (length == x.length) && (theSeq sameElements x.theSeq) - case _ => false - } - - /** Projection function, which returns elements of `this` sequence based - * on the string `that`. Use: - * - `this \ "foo"` to get a list of all elements that are labelled with `"foo"`; - * - `\ "_"` to get a list of all elements (wildcard); - * - `ns \ "@foo"` to get the unprefixed attribute `"foo"`; - * - `ns \ "@{uri}foo"` to get the prefixed attribute `"pre:foo"` whose - * prefix `"pre"` is resolved to the namespace `"uri"`. - * - * For attribute projections, the resulting [[scala.xml.NodeSeq]] attribute - * values are wrapped in a [[scala.xml.Group]]. - * - * There is no support for searching a prefixed attribute by its literal prefix. - * - * The document order is preserved. - */ - def \(that: String): NodeSeq = { - def fail = throw new IllegalArgumentException(that) - def atResult = { - lazy val y = this(0) - val attr = - if (that.length == 1) fail - else if (that(1) == '{') { - val i = that indexOf '}' - if (i == -1) fail - val (uri, key) = (that.substring(2,i), that.substring(i+1, that.length())) - if (uri == "" || key == "") fail - else y.attribute(uri, key) - } - else y.attribute(that drop 1) - - attr match { - case Some(x) => Group(x) - case _ => NodeSeq.Empty - } - } - - def makeSeq(cond: (Node) => Boolean) = - NodeSeq fromSeq (this flatMap (_.child) filter cond) - - that match { - case "" => fail - case "_" => makeSeq(!_.isAtom) - case _ if (that(0) == '@' && this.length == 1) => atResult - case _ => makeSeq(_.label == that) - } - } - - /** Projection function, which returns elements of `this` sequence and of - * all its subsequences, based on the string `that`. Use: - * - `this \\ 'foo` to get a list of all elements that are labelled with `"foo"`; - * - `\\ "_"` to get a list of all elements (wildcard); - * - `ns \\ "@foo"` to get the unprefixed attribute `"foo"`; - * - `ns \\ "@{uri}foo"` to get each prefixed attribute `"pre:foo"` whose - * prefix `"pre"` is resolved to the namespace `"uri"`. - * - * For attribute projections, the resulting [[scala.xml.NodeSeq]] attribute - * values are wrapped in a [[scala.xml.Group]]. - * - * There is no support for searching a prefixed attribute by its literal prefix. - * - * The document order is preserved. - */ - def \\ (that: String): NodeSeq = { - def filt(cond: (Node) => Boolean) = this flatMap (_.descendant_or_self) filter cond - that match { - case "_" => filt(!_.isAtom) - case _ if that(0) == '@' => filt(!_.isAtom) flatMap (_ \ that) - case _ => filt(x => !x.isAtom && x.label == that) - } - } - - override def toString(): String = theSeq.mkString - - def text: String = (this map (_.text)).mkString -} diff --git a/src/library/scala/xml/Null.scala b/src/library/scala/xml/Null.scala deleted file mode 100644 index b39ef5dc67..0000000000 --- a/src/library/scala/xml/Null.scala +++ /dev/null @@ -1,61 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala.xml - -import Utility.isNameStart -import scala.collection.Iterator - -/** Essentially, every method in here is a dummy, returning Zero[T]. - * It provides a backstop for the unusual collection defined by MetaData, - * sort of a linked list of tails. - * - * @author Burak Emir - * @version 1.0 - */ -case object Null extends MetaData { - override def iterator = Iterator.empty - override def size = 0 - override def append(m: MetaData, scope: NamespaceBinding = TopScope): MetaData = m - override def filter(f: MetaData => Boolean): MetaData = this - - def copy(next: MetaData) = next - def getNamespace(owner: Node) = null - - override def hasNext = false - def next = null - def key = null - def value = null - def isPrefixed = false - - override def length = 0 - override def length(i: Int) = i - - override def strict_==(other: Equality) = other match { - case x: MetaData => x.length == 0 - case _ => false - } - override protected def basisForHashCode: Seq[Any] = Nil - - def apply(namespace: String, scope: NamespaceBinding, key: String) = null - def apply(key: String) = - if (isNameStart(key.head)) null - else throw new IllegalArgumentException("not a valid attribute name '"+key+"', so can never match !") - - protected def toString1(sb: StringBuilder) = () - override protected def toString1(): String = "" - - override def toString(): String = "" - - override def buildString(sb: StringBuilder): StringBuilder = sb - - override def wellformed(scope: NamespaceBinding) = true - - def remove(key: String) = this - def remove(namespace: String, scope: NamespaceBinding, key: String) = this -} diff --git a/src/library/scala/xml/PCData.scala b/src/library/scala/xml/PCData.scala deleted file mode 100644 index 64818a9c00..0000000000 --- a/src/library/scala/xml/PCData.scala +++ /dev/null @@ -1,43 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala.xml - -/** This class (which is not used by all XML parsers, but always used by the - * XHTML one) represents parseable character data, which appeared as CDATA - * sections in the input and is to be preserved as CDATA section in the output. - * - * @author Burak Emir - * @version 1.0 - */ -class PCData(data: String) extends Atom[String](data) { - - /** Returns text, with some characters escaped according to the XML - * specification. - * - * @param sb the input string buffer associated to some XML element - * @return the input string buffer with the formatted CDATA section - */ - override def buildString(sb: StringBuilder): StringBuilder = - sb append "<![CDATA[%s]]>".format(data) -} - -/** This singleton object contains the `apply`and `unapply` methods for - * convenient construction and deconstruction. - * - * @author Burak Emir - * @version 1.0 - */ -object PCData { - def apply(data: String) = new PCData(data) - def unapply(other: Any): Option[String] = other match { - case x: PCData => Some(x.data) - case _ => None - } -} - diff --git a/src/library/scala/xml/PrefixedAttribute.scala b/src/library/scala/xml/PrefixedAttribute.scala deleted file mode 100644 index 429cd682d6..0000000000 --- a/src/library/scala/xml/PrefixedAttribute.scala +++ /dev/null @@ -1,60 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - -package scala.xml - -/** prefixed attributes always have a non-null namespace. - * - * @param pre - * @param key - * @param value the attribute value - * @param next1 - */ -class PrefixedAttribute( - val pre: String, - val key: String, - val value: Seq[Node], - val next1: MetaData) -extends Attribute -{ - val next = if (value ne null) next1 else next1.remove(key) - - /** same as this(pre, key, Text(value), next), or no attribute if value is null */ - def this(pre: String, key: String, value: String, next: MetaData) = - this(pre, key, if (value ne null) Text(value) else null: NodeSeq, next) - - /** same as this(pre, key, value.get, next), or no attribute if value is None */ - def this(pre: String, key: String, value: Option[Seq[Node]], next: MetaData) = - this(pre, key, value.orNull, next) - - /** Returns a copy of this unprefixed attribute with the given - * next field. - */ - def copy(next: MetaData) = - new PrefixedAttribute(pre, key, value, next) - - def getNamespace(owner: Node) = - owner.getNamespace(pre) - - /** forwards the call to next (because caller looks for unprefixed attribute */ - def apply(key: String): Seq[Node] = next(key) - - /** gets attribute value of qualified (prefixed) attribute with given key - */ - def apply(namespace: String, scope: NamespaceBinding, key: String): Seq[Node] = { - if (key == this.key && scope.getURI(pre) == namespace) - value - else - next(namespace, scope, key) - } -} - -object PrefixedAttribute { - def unapply(x: PrefixedAttribute) = Some((x.pre, x.key, x.value, x.next)) -} diff --git a/src/library/scala/xml/PrettyPrinter.scala b/src/library/scala/xml/PrettyPrinter.scala deleted file mode 100755 index 39ff8c35ec..0000000000 --- a/src/library/scala/xml/PrettyPrinter.scala +++ /dev/null @@ -1,263 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala.xml - -import Utility.sbToString - -/** Class for pretty printing. After instantiating, you can use the - * format() and formatNode() methods to convert XML to a formatted - * string. The class can be reused to pretty print any number of - * XML nodes. - * - * @author Burak Emir - * @version 1.0 - * - * @param width the width to fit the output into - * @param step indentation - */ -class PrettyPrinter(width: Int, step: Int) { - - class BrokenException() extends java.lang.Exception - - class Item - case object Break extends Item { - override def toString() = "\\" - } - case class Box(col: Int, s: String) extends Item - case class Para(s: String) extends Item - - protected var items: List[Item] = Nil - - protected var cur = 0 - - protected def reset() = { - cur = 0 - items = Nil - } - - /** Try to cut at whitespace. - */ - protected def cut(s: String, ind: Int): List[Item] = { - val tmp = width - cur - if (s.length <= tmp) - return List(Box(ind, s)) - val sb = new StringBuilder() - var i = s indexOf ' ' - if (i > tmp || i == -1) throw new BrokenException() // cannot break - - var last: List[Int] = Nil - while (i != -1 && i < tmp) { - last = i::last - i = s.indexOf(' ', i+1) - } - var res: List[Item] = Nil - while (Nil != last) try { - val b = Box(ind, s.substring(0, last.head)) - cur = ind - res = b :: Break :: cut(s.substring(last.head, s.length), ind) - // backtrack - last = last.tail - } catch { - case _:BrokenException => last = last.tail - } - throw new BrokenException() - } - - /** Try to make indented box, if possible, else para. - */ - protected def makeBox(ind: Int, s: String) = - if (cur + s.length > width) { // fits in this line - items ::= Box(ind, s) - cur += s.length - } - else try cut(s, ind) foreach (items ::= _) // break it up - catch { case _: BrokenException => makePara(ind, s) } // give up, para - - // dont respect indent in para, but afterwards - protected def makePara(ind: Int, s: String) = { - items = Break::Para(s)::Break::items - cur = ind - } - - // respect indent - protected def makeBreak() = { // using wrapping here... - items = Break :: items - cur = 0 - } - - protected def leafTag(n: Node) = { - def mkLeaf(sb: StringBuilder) { - sb append '<' - n nameToString sb - n.attributes buildString sb - sb append "/>" - } - sbToString(mkLeaf) - } - - protected def startTag(n: Node, pscope: NamespaceBinding): (String, Int) = { - var i = 0 - def mkStart(sb: StringBuilder) { - sb append '<' - n nameToString sb - i = sb.length + 1 - n.attributes buildString sb - n.scope.buildString(sb, pscope) - sb append '>' - } - (sbToString(mkStart), i) - } - - protected def endTag(n: Node) = { - def mkEnd(sb: StringBuilder) { - sb append "</" - n nameToString sb - sb append '>' - } - sbToString(mkEnd) - } - - protected def childrenAreLeaves(n: Node): Boolean = { - def isLeaf(l: Node) = l match { - case _:Atom[_] | _:Comment | _:EntityRef | _:ProcInstr => true - case _ => false - } - n.child forall isLeaf - } - - protected def fits(test: String) = - test.length < width - cur - - private def doPreserve(node: Node) = - node.attribute(XML.namespace, XML.space).map(_.toString == XML.preserve) getOrElse false - - protected def traverse(node: Node, pscope: NamespaceBinding, ind: Int): Unit = node match { - - case Text(s) if s.trim() == "" => - ; - case _:Atom[_] | _:Comment | _:EntityRef | _:ProcInstr => - makeBox( ind, node.toString.trim() ) - case g @ Group(xs) => - traverse(xs.iterator, pscope, ind) - case _ => - val test = { - val sb = new StringBuilder() - Utility.serialize(node, pscope, sb, false) - if (doPreserve(node)) sb.toString - else TextBuffer.fromString(sb.toString).toText(0).data - } - if (childrenAreLeaves(node) && fits(test)) { - makeBox(ind, test) - } else { - val (stg, len2) = startTag(node, pscope) - val etg = endTag(node) - if (stg.length < width - cur) { // start tag fits - makeBox(ind, stg) - makeBreak() - traverse(node.child.iterator, node.scope, ind + step) - makeBox(ind, etg) - } else if (len2 < width - cur) { - // <start label + attrs + tag + content + end tag - makeBox(ind, stg.substring(0, len2)) - makeBreak() // todo: break the rest in pieces - /*{ //@todo - val sq:Seq[String] = stg.split(" "); - val it = sq.iterator; - it.next; - for (c <- it) { - makeBox(ind+len2-2, c) - makeBreak() - } - }*/ - makeBox(ind, stg.substring(len2, stg.length)) - makeBreak() - traverse(node.child.iterator, node.scope, ind + step) - makeBox(cur, etg) - makeBreak() - } else { // give up - makeBox(ind, test) - makeBreak() - } - } - } - - protected def traverse(it: Iterator[Node], scope: NamespaceBinding, ind: Int ): Unit = - for (c <- it) { - traverse(c, scope, ind) - makeBreak() - } - - /** Appends a formatted string containing well-formed XML with - * given namespace to prefix mapping to the given string buffer. - * - * @param n the node to be serialized - * @param sb the stringbuffer to append to - */ - def format(n: Node, sb: StringBuilder) { // entry point - format(n, null, sb) - } - - def format(n: Node, pscope: NamespaceBinding, sb: StringBuilder) { // entry point - var lastwasbreak = false - reset() - traverse(n, pscope, 0) - var cur = 0 - for (b <- items.reverse) b match { - case Break => - if (!lastwasbreak) sb.append('\n') // on windows: \r\n ? - lastwasbreak = true - cur = 0 -// while (cur < last) { -// sb append ' ' -// cur += 1 -// } - - case Box(i, s) => - lastwasbreak = false - while (cur < i) { - sb append ' ' - cur += 1 - } - sb.append(s) - case Para( s ) => - lastwasbreak = false - sb append s - } - } - - // public convenience methods - - /** Returns a formatted string containing well-formed XML with - * given namespace to prefix mapping. - * - * @param n the node to be serialized - * @param pscope the namespace to prefix mapping - * @return the formatted string - */ - def format(n: Node, pscope: NamespaceBinding = null): String = - sbToString(format(n, pscope, _)) - - /** Returns a formatted string containing well-formed XML. - * - * @param nodes the sequence of nodes to be serialized - * @param pscope the namespace to prefix mapping - */ - def formatNodes(nodes: Seq[Node], pscope: NamespaceBinding = null): String = - sbToString(formatNodes(nodes, pscope, _)) - - /** Appends a formatted string containing well-formed XML with - * the given namespace to prefix mapping to the given stringbuffer. - * - * @param nodes the nodes to be serialized - * @param pscope the namespace to prefix mapping - * @param sb the string buffer to which to append to - */ - def formatNodes(nodes: Seq[Node], pscope: NamespaceBinding, sb: StringBuilder): Unit = - nodes foreach (n => sb append format(n, pscope)) -} diff --git a/src/library/scala/xml/ProcInstr.scala b/src/library/scala/xml/ProcInstr.scala deleted file mode 100644 index 64a9dd5ca3..0000000000 --- a/src/library/scala/xml/ProcInstr.scala +++ /dev/null @@ -1,38 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - -package scala.xml - -/** an XML node for processing instructions (PI) - * - * @author Burak Emir - * @param target target name of this PI - * @param proctext text contained in this node, may not contain "?>" - */ -case class ProcInstr(target: String, proctext: String) extends SpecialNode -{ - if (!Utility.isName(target)) - throw new IllegalArgumentException(target+" must be an XML Name") - if (proctext contains "?>") - throw new IllegalArgumentException(proctext+" may not contain \"?>\"") - if (target.toLowerCase == "xml") - throw new IllegalArgumentException(target+" is reserved") - - final override def doCollectNamespaces = false - final override def doTransform = false - - final def label = "#PI" - override def text = "" - - /** appends "<?" target (" "+text)?+"?>" - * to this stringbuffer. - */ - override def buildString(sb: StringBuilder) = - sb append "<?%s%s?>".format(target, (if (proctext == "") "" else " " + proctext)) -} diff --git a/src/library/scala/xml/QNode.scala b/src/library/scala/xml/QNode.scala deleted file mode 100644 index d4d3872181..0000000000 --- a/src/library/scala/xml/QNode.scala +++ /dev/null @@ -1,19 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala.xml - -/** This object provides an extractor method to match a qualified node with - * its namespace URI - * - * @author Burak Emir - * @version 1.0 - */ -object QNode { - def unapplySeq(n: Node) = Some((n.scope.getURI(n.prefix), n.label, n.attributes, n.child)) -} diff --git a/src/library/scala/xml/SpecialNode.scala b/src/library/scala/xml/SpecialNode.scala deleted file mode 100644 index 4c1b81c7ff..0000000000 --- a/src/library/scala/xml/SpecialNode.scala +++ /dev/null @@ -1,32 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala.xml - -/** `SpecialNode` is a special XML node which represents either text - * `(PCDATA)`, a comment, a `PI`, or an entity ref. - * - * `SpecialNode`s also play the role of [[scala.xml.pull.XMLEvent]]s for - * pull-parsing. - * - * @author Burak Emir - */ -abstract class SpecialNode extends Node with pull.XMLEvent { - - /** always empty */ - final override def attributes = Null - - /** always Node.EmptyNamespace */ - final override def namespace = null - - /** always empty */ - final def child = Nil - - /** Append string representation to the given string buffer argument. */ - def buildString(sb: StringBuilder): StringBuilder -} diff --git a/src/library/scala/xml/Text.scala b/src/library/scala/xml/Text.scala deleted file mode 100644 index 782c80f100..0000000000 --- a/src/library/scala/xml/Text.scala +++ /dev/null @@ -1,38 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala.xml - -/** The class `Text` implements an XML node for text (PCDATA). - * It is used in both non-bound and bound XML representations. - * - * @author Burak Emir - * @param data the text contained in this node, may not be null. - */ -class Text(data: String) extends Atom[String](data) { - - /** Returns text, with some characters escaped according to the XML - * specification. - */ - override def buildString(sb: StringBuilder): StringBuilder = - Utility.escape(data, sb) -} - -/** This singleton object contains the `apply`and `unapply` methods for - * convenient construction and deconstruction. - * - * @author Burak Emir - * @version 1.0 - */ -object Text { - def apply(data: String) = new Text(data) - def unapply(other: Any): Option[String] = other match { - case x: Text => Some(x.data) - case _ => None - } -} diff --git a/src/library/scala/xml/TextBuffer.scala b/src/library/scala/xml/TextBuffer.scala deleted file mode 100644 index 0b96379d85..0000000000 --- a/src/library/scala/xml/TextBuffer.scala +++ /dev/null @@ -1,45 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - -package scala.xml - -import Utility.isSpace - -object TextBuffer { - def fromString(str: String): TextBuffer = new TextBuffer() append str -} - -/** The class `TextBuffer` is for creating text nodes without surplus - * whitespace. All occurrences of one or more whitespace in strings - * appended with the `append` method will be replaced by a single space - * character, and leading and trailing space will be removed completely. - */ -class TextBuffer -{ - val sb = new StringBuilder() - - /** Appends this string to the text buffer, trimming whitespaces as needed. - */ - def append(cs: Seq[Char]): this.type = { - cs foreach { c => - if (!isSpace(c)) sb append c - else if (sb.isEmpty || !isSpace(sb.last)) sb append ' ' - } - this - } - - /** Returns an empty sequence if text is only whitespace. - * - * @return the text without whitespaces. - */ - def toText: Seq[Text] = sb.toString.trim match { - case "" => Nil - case s => Seq(Text(s)) - } -} diff --git a/src/library/scala/xml/TopScope.scala b/src/library/scala/xml/TopScope.scala deleted file mode 100644 index 1ed1d50e10..0000000000 --- a/src/library/scala/xml/TopScope.scala +++ /dev/null @@ -1,30 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - -package scala.xml - -/** top level namespace scope. only contains the predefined binding - * for the "xml" prefix which is bound to - * "http://www.w3.org/XML/1998/namespace" - */ -object TopScope extends NamespaceBinding(null, null, null) { - - import XML.{ xml, namespace } - - override def getURI(prefix1: String): String = - if (prefix1 == xml) namespace else null - - override def getPrefix(uri1: String): String = - if (uri1 == namespace) xml else null - - override def toString() = "" - - override def buildString(stop: NamespaceBinding) = "" - override def buildString(sb: StringBuilder, ignore: NamespaceBinding) = {} -} diff --git a/src/library/scala/xml/TypeSymbol.scala b/src/library/scala/xml/TypeSymbol.scala deleted file mode 100644 index f02c0263c0..0000000000 --- a/src/library/scala/xml/TypeSymbol.scala +++ /dev/null @@ -1,14 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - - -package scala.xml - - -abstract class TypeSymbol diff --git a/src/library/scala/xml/Unparsed.scala b/src/library/scala/xml/Unparsed.scala deleted file mode 100644 index ef80823611..0000000000 --- a/src/library/scala/xml/Unparsed.scala +++ /dev/null @@ -1,35 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala.xml - -/** An XML node for unparsed content. It will be output verbatim, all bets - * are off regarding wellformedness etc. - * - * @author Burak Emir - * @param data content in this node, may not be null. - */ -class Unparsed(data: String) extends Atom[String](data) { - - /** Returns text, with some characters escaped according to XML - * specification. - */ - override def buildString(sb: StringBuilder): StringBuilder = - sb append data -} - -/** This singleton object contains the `apply`and `unapply` methods for - * convenient construction and deconstruction. - * - * @author Burak Emir - * @version 1.0 - */ -object Unparsed { - def apply(data: String) = new Unparsed(data) - def unapply(x: Unparsed) = Some(x.data) -} diff --git a/src/library/scala/xml/UnprefixedAttribute.scala b/src/library/scala/xml/UnprefixedAttribute.scala deleted file mode 100644 index 2985591c95..0000000000 --- a/src/library/scala/xml/UnprefixedAttribute.scala +++ /dev/null @@ -1,60 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - -package scala.xml - -/** Unprefixed attributes have the null namespace, and no prefix field - * - * @author Burak Emir - */ -class UnprefixedAttribute( - val key: String, - val value: Seq[Node], - next1: MetaData) -extends Attribute -{ - final val pre = null - val next = if (value ne null) next1 else next1.remove(key) - - /** same as this(key, Text(value), next), or no attribute if value is null */ - def this(key: String, value: String, next: MetaData) = - this(key, if (value ne null) Text(value) else null: NodeSeq, next) - - /** same as this(key, value.get, next), or no attribute if value is None */ - def this(key: String, value: Option[Seq[Node]], next: MetaData) = - this(key, value.orNull, next) - - /** returns a copy of this unprefixed attribute with the given next field*/ - def copy(next: MetaData) = new UnprefixedAttribute(key, value, next) - - final def getNamespace(owner: Node): String = null - - /** - * Gets value of unqualified (unprefixed) attribute with given key, null if not found - * - * @param key - * @return value as Seq[Node] if key is found, null otherwise - */ - def apply(key: String): Seq[Node] = - if (key == this.key) value else next(key) - - /** - * Forwards the call to next (because caller looks for prefixed attribute). - * - * @param namespace - * @param scope - * @param key - * @return .. - */ - def apply(namespace: String, scope: NamespaceBinding, key: String): Seq[Node] = - next(namespace, scope, key) -} -object UnprefixedAttribute { - def unapply(x: UnprefixedAttribute) = Some((x.key, x.value, x.next)) -} diff --git a/src/library/scala/xml/Utility.scala b/src/library/scala/xml/Utility.scala deleted file mode 100755 index 030a89773e..0000000000 --- a/src/library/scala/xml/Utility.scala +++ /dev/null @@ -1,409 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala.xml - -import scala.collection.mutable -import parsing.XhtmlEntities -import scala.language.implicitConversions - -/** - * The `Utility` object provides utility functions for processing instances - * of bound and not bound XML classes, as well as escaping text nodes. - * - * @author Burak Emir - */ -object Utility extends AnyRef with parsing.TokenTests { - final val SU = '\u001A' - - // [Martin] This looks dubious. We don't convert StringBuilders to - // Strings anywhere else, why do it here? - implicit def implicitSbToString(sb: StringBuilder) = sb.toString() - - // helper for the extremely oft-repeated sequence of creating a - // StringBuilder, passing it around, and then grabbing its String. - private [xml] def sbToString(f: (StringBuilder) => Unit): String = { - val sb = new StringBuilder - f(sb) - sb.toString - } - private[xml] def isAtomAndNotText(x: Node) = x.isAtom && !x.isInstanceOf[Text] - - /** Trims an element - call this method, when you know that it is an - * element (and not a text node) so you know that it will not be trimmed - * away. With this assumption, the function can return a `Node`, rather - * than a `Seq[Node]`. If you don't know, call `trimProper` and account - * for the fact that you may get back an empty sequence of nodes. - * - * Precondition: node is not a text node (it might be trimmed) - */ - def trim(x: Node): Node = x match { - case Elem(pre, lab, md, scp, child@_*) => - Elem(pre, lab, md, scp, (child flatMap trimProper):_*) - } - - /** trim a child of an element. `Attribute` values and `Atom` nodes that - * are not `Text` nodes are unaffected. - */ - def trimProper(x:Node): Seq[Node] = x match { - case Elem(pre,lab,md,scp,child@_*) => - Elem(pre,lab,md,scp, (child flatMap trimProper):_*) - case Text(s) => - new TextBuffer().append(s).toText - case _ => - x - } - - /** returns a sorted attribute list */ - def sort(md: MetaData): MetaData = if((md eq Null) || (md.next eq Null)) md else { - val key = md.key - val smaller = sort(md.filter { m => m.key < key }) - val greater = sort(md.filter { m => m.key > key }) - smaller.foldRight (md copy greater) ((x, xs) => x copy xs) - } - - /** Return the node with its attribute list sorted alphabetically - * (prefixes are ignored) */ - def sort(n:Node): Node = n match { - case Elem(pre,lab,md,scp,child@_*) => - Elem(pre,lab,sort(md),scp, (child map sort):_*) - case _ => n - } - - /** - * Escapes the characters < > & and " from string. - */ - final def escape(text: String): String = sbToString(escape(text, _)) - - object Escapes { - /** For reasons unclear escape and unescape are a long ways from - * being logical inverses. */ - val pairs = Map( - "lt" -> '<', - "gt" -> '>', - "amp" -> '&', - "quot" -> '"' - // enigmatic comment explaining why this isn't escaped -- - // is valid xhtml but not html, and IE doesn't know it, says jweb - // "apos" -> '\'' - ) - val escMap = pairs map { case (s, c) => c-> ("&%s;" format s) } - val unescMap = pairs ++ Map("apos" -> '\'') - } - import Escapes.{ escMap, unescMap } - - /** - * Appends escaped string to `s`. - */ - final def escape(text: String, s: StringBuilder): StringBuilder = { - // Implemented per XML spec: - // http://www.w3.org/International/questions/qa-controls - // imperative code 3x-4x faster than current implementation - // dpp (David Pollak) 2010/02/03 - val len = text.length - var pos = 0 - while (pos < len) { - text.charAt(pos) match { - case '<' => s.append("<") - case '>' => s.append(">") - case '&' => s.append("&") - case '"' => s.append(""") - case '\n' => s.append('\n') - case '\r' => s.append('\r') - case '\t' => s.append('\t') - case c => if (c >= ' ') s.append(c) - } - - pos += 1 - } - s - } - - /** - * Appends unescaped string to `s`, `amp` becomes `&`, - * `lt` becomes `<` etc.. - * - * @return `'''null'''` if `ref` was not a predefined entity. - */ - final def unescape(ref: String, s: StringBuilder): StringBuilder = - ((unescMap get ref) map (s append _)).orNull - - /** - * Returns a set of all namespaces used in a sequence of nodes - * and all their descendants, including the empty namespaces. - */ - def collectNamespaces(nodes: Seq[Node]): mutable.Set[String] = - nodes.foldLeft(new mutable.HashSet[String]) { (set, x) => collectNamespaces(x, set) ; set } - - /** - * Adds all namespaces in node to set. - */ - def collectNamespaces(n: Node, set: mutable.Set[String]) { - if (n.doCollectNamespaces) { - set += n.namespace - for (a <- n.attributes) a match { - case _:PrefixedAttribute => - set += a.getNamespace(n) - case _ => - } - for (i <- n.child) - collectNamespaces(i, set) - } - } - - // def toXML( - // x: Node, - // pscope: NamespaceBinding = TopScope, - // sb: StringBuilder = new StringBuilder, - // stripComments: Boolean = false, - // decodeEntities: Boolean = true, - // preserveWhitespace: Boolean = false, - // minimizeTags: Boolean = false): String = - // { - // toXMLsb(x, pscope, sb, stripComments, decodeEntities, preserveWhitespace, minimizeTags) - // sb.toString() - // } - - /** - * Serialize the provided Node to the provided StringBuilder. - * <p/> - * Note that calling this source-compatible method will result in the same old, arguably almost universally unwanted, - * behaviour. - */ - @deprecated("Please use `serialize` instead and specify a `minimizeTags` parameter", "2.10.0") - def toXML( - x: Node, - pscope: NamespaceBinding = TopScope, - sb: StringBuilder = new StringBuilder, - stripComments: Boolean = false, - decodeEntities: Boolean = true, - preserveWhitespace: Boolean = false, - minimizeTags: Boolean = false): StringBuilder = - { - serialize(x, pscope, sb, stripComments, decodeEntities, preserveWhitespace, if (minimizeTags) MinimizeMode.Always else MinimizeMode.Never) - } - - /** - * Serialize an XML Node to a StringBuilder. - * - * This is essentially a minor rework of `toXML` that can't have the same name due to an unfortunate - * combination of named/default arguments and overloading. - * - * @todo use a Writer instead - */ - def serialize( - x: Node, - pscope: NamespaceBinding = TopScope, - sb: StringBuilder = new StringBuilder, - stripComments: Boolean = false, - decodeEntities: Boolean = true, - preserveWhitespace: Boolean = false, - minimizeTags: MinimizeMode.Value = MinimizeMode.Default): StringBuilder = - { - x match { - case c: Comment if !stripComments => c buildString sb - case s: SpecialNode => s buildString sb - case g: Group => for (c <- g.nodes) serialize(c, g.scope, sb, minimizeTags = minimizeTags) ; sb - case el: Elem => - // print tag with namespace declarations - sb.append('<') - el.nameToString(sb) - if (el.attributes ne null) el.attributes.buildString(sb) - el.scope.buildString(sb, pscope) - if (el.child.isEmpty && - (minimizeTags == MinimizeMode.Always || - (minimizeTags == MinimizeMode.Default && el.minimizeEmpty))) - { - // no children, so use short form: <xyz .../> - sb.append("/>") - } else { - // children, so use long form: <xyz ...>...</xyz> - sb.append('>') - sequenceToXML(el.child, el.scope, sb, stripComments) - sb.append("</") - el.nameToString(sb) - sb.append('>') - } - case _ => throw new IllegalArgumentException("Don't know how to serialize a " + x.getClass.getName) - } - } - - def sequenceToXML( - children: Seq[Node], - pscope: NamespaceBinding = TopScope, - sb: StringBuilder = new StringBuilder, - stripComments: Boolean = false, - decodeEntities: Boolean = true, - preserveWhitespace: Boolean = false, - minimizeTags: MinimizeMode.Value = MinimizeMode.Default): Unit = - { - if (children.isEmpty) return - else if (children forall isAtomAndNotText) { // add space - val it = children.iterator - val f = it.next - serialize(f, pscope, sb, stripComments, decodeEntities, preserveWhitespace, minimizeTags) - while (it.hasNext) { - val x = it.next - sb.append(' ') - serialize(x, pscope, sb, stripComments, decodeEntities, preserveWhitespace, minimizeTags) - } - } - else children foreach { serialize(_, pscope, sb, stripComments, decodeEntities, preserveWhitespace, minimizeTags) } - } - - /** - * Returns prefix of qualified name if any. - */ - final def prefix(name: String): Option[String] = (name indexOf ':') match { - case -1 => None - case i => Some(name.substring(0, i)) - } - - /** - * Returns a hashcode for the given constituents of a node - */ - def hashCode(pre: String, label: String, attribHashCode: Int, scpeHash: Int, children: Seq[Node]) = - scala.util.hashing.MurmurHash3.orderedHash(label +: attribHashCode +: scpeHash +: children, pre.##) - - def appendQuoted(s: String): String = sbToString(appendQuoted(s, _)) - - /** - * Appends "s" if string `s` does not contain ", - * 's' otherwise. - */ - def appendQuoted(s: String, sb: StringBuilder) = { - val ch = if (s contains '"') '\'' else '"' - sb.append(ch).append(s).append(ch) - } - - /** - * Appends "s" and escapes and " i s with \" - */ - def appendEscapedQuoted(s: String, sb: StringBuilder): StringBuilder = { - sb.append('"') - for (c <- s) c match { - case '"' => sb.append('\\'); sb.append('"') - case _ => sb.append(c) - } - sb.append('"') - } - - def getName(s: String, index: Int): String = { - if (index >= s.length) null - else { - val xs = s drop index - if (xs.nonEmpty && isNameStart(xs.head)) xs takeWhile isNameChar - else "" - } - } - - /** - * Returns `'''null'''` if the value is a correct attribute value, - * error message if it isn't. - */ - def checkAttributeValue(value: String): String = { - var i = 0 - while (i < value.length) { - value.charAt(i) match { - case '<' => - return "< not allowed in attribute value"; - case '&' => - val n = getName(value, i+1) - if (n eq null) - return "malformed entity reference in attribute value ["+value+"]"; - i = i + n.length + 1 - if (i >= value.length || value.charAt(i) != ';') - return "malformed entity reference in attribute value ["+value+"]"; - case _ => - } - i = i + 1 - } - null - } - - def parseAttributeValue(value: String): Seq[Node] = { - val sb = new StringBuilder - var rfb: StringBuilder = null - val nb = new NodeBuffer() - - val it = value.iterator - while (it.hasNext) { - var c = it.next - // entity! flush buffer into text node - if (c == '&') { - c = it.next - if (c == '#') { - c = it.next - val theChar = parseCharRef ({ ()=> c },{ () => c = it.next },{s => throw new RuntimeException(s)}, {s => throw new RuntimeException(s)}) - sb.append(theChar) - } - else { - if (rfb eq null) rfb = new StringBuilder() - rfb append c - c = it.next - while (c != ';') { - rfb.append(c) - c = it.next - } - val ref = rfb.toString() - rfb.clear() - unescape(ref,sb) match { - case null => - if (sb.length > 0) { // flush buffer - nb += Text(sb.toString()) - sb.clear() - } - nb += EntityRef(ref) // add entityref - case _ => - } - } - } - else sb append c - } - if (sb.length > 0) { // flush buffer - val x = Text(sb.toString()) - if (nb.length == 0) - return x - else - nb += x - } - nb - } - - /** - * {{{ - * CharRef ::= "&#" '0'..'9' {'0'..'9'} ";" - * | "&#x" '0'..'9'|'A'..'F'|'a'..'f' { hexdigit } ";" - * }}} - * See [66] - */ - def parseCharRef(ch: () => Char, nextch: () => Unit, reportSyntaxError: String => Unit, reportTruncatedError: String => Unit): String = { - val hex = (ch() == 'x') && { nextch(); true } - val base = if (hex) 16 else 10 - var i = 0 - while (ch() != ';') { - ch() match { - case '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' => - i = i * base + ch().asDigit - case 'a' | 'b' | 'c' | 'd' | 'e' | 'f' - | 'A' | 'B' | 'C' | 'D' | 'E' | 'F' => - if (! hex) - reportSyntaxError("hex char not allowed in decimal char ref\n" + - "Did you mean to write &#x ?") - else - i = i * base + ch().asDigit - case SU => - reportTruncatedError("") - case _ => - reportSyntaxError("character '" + ch() + "' not allowed in char ref\n") - } - nextch() - } - new String(Array(i), 0, 1) - } -} diff --git a/src/library/scala/xml/XML.scala b/src/library/scala/xml/XML.scala deleted file mode 100755 index d101684459..0000000000 --- a/src/library/scala/xml/XML.scala +++ /dev/null @@ -1,110 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala.xml - -import parsing.NoBindingFactoryAdapter -import factory.XMLLoader -import java.io.{ File, FileDescriptor, FileInputStream, FileOutputStream } -import java.io.{ InputStream, Reader, StringReader, Writer } -import java.nio.channels.Channels -import scala.util.control.Exception.ultimately - -object Source { - def fromFile(file: File) = new InputSource(new FileInputStream(file)) - def fromFile(fd: FileDescriptor) = new InputSource(new FileInputStream(fd)) - def fromFile(name: String) = new InputSource(new FileInputStream(name)) - - def fromInputStream(is: InputStream) = new InputSource(is) - def fromReader(reader: Reader) = new InputSource(reader) - def fromSysId(sysID: String) = new InputSource(sysID) - def fromString(string: String) = fromReader(new StringReader(string)) -} - -/** - * Governs how empty elements (i.e. those without child elements) should be serialized. - */ -object MinimizeMode extends Enumeration { - /** Minimize empty tags if they were originally empty when parsed, or if they were constructed - * with [[scala.xml.Elem]]`#minimizeEmpty` == true - */ - val Default = Value - - /** Always minimize empty tags. Note that this may be problematic for XHTML, in which - * case [[scala.xml.Xhtml]]`#toXhtml` should be used instead. - */ - val Always = Value - - /** Never minimize empty tags. - */ - val Never = Value -} - -import Source._ - -/** The object `XML` provides constants, and functions to load - * and save XML elements. Use this when data binding is not desired, i.e. - * when XML is handled using `Symbol` nodes. - * - * @author Burak Emir - * @version 1.0, 25/04/2005 - */ -object XML extends XMLLoader[Elem] { - val xml = "xml" - val xmlns = "xmlns" - val namespace = "http://www.w3.org/XML/1998/namespace" - val preserve = "preserve" - val space = "space" - val lang = "lang" - val encoding = "ISO-8859-1" - - /** Returns an XMLLoader whose load* methods will use the supplied SAXParser. */ - def withSAXParser(p: SAXParser): XMLLoader[Elem] = - new XMLLoader[Elem] { override val parser: SAXParser = p } - - /** Saves a node to a file with given filename using given encoding - * optionally with xmldecl and doctype declaration. - * - * @param filename the filename - * @param node the xml node we want to write - * @param enc encoding to use - * @param xmlDecl if true, write xml declaration - * @param doctype if not null, write doctype declaration - */ - final def save( - filename: String, - node: Node, - enc: String = encoding, - xmlDecl: Boolean = false, - doctype: dtd.DocType = null - ): Unit = - { - val fos = new FileOutputStream(filename) - val w = Channels.newWriter(fos.getChannel(), enc) - - ultimately(w.close())( - write(w, node, enc, xmlDecl, doctype) - ) - } - - /** Writes the given node using writer, optionally with xml decl and doctype. - * It's the caller's responsibility to close the writer. - * - * @param w the writer - * @param node the xml node we want to write - * @param enc the string to be used in `xmlDecl` - * @param xmlDecl if true, write xml declaration - * @param doctype if not null, write doctype declaration - */ - final def write(w: java.io.Writer, node: Node, enc: String, xmlDecl: Boolean, doctype: dtd.DocType, minimizeTags: MinimizeMode.Value = MinimizeMode.Default) { - /* TODO: optimize by giving writer parameter to toXML*/ - if (xmlDecl) w.write("<?xml version='1.0' encoding='" + enc + "'?>\n") - if (doctype ne null) w.write( doctype.toString() + "\n") - w.write(Utility.serialize(node, minimizeTags = minimizeTags).toString) - } -} diff --git a/src/library/scala/xml/Xhtml.scala b/src/library/scala/xml/Xhtml.scala deleted file mode 100644 index 6730548b73..0000000000 --- a/src/library/scala/xml/Xhtml.scala +++ /dev/null @@ -1,96 +0,0 @@ - -package scala.xml - -import parsing.XhtmlEntities -import Utility.{ sbToString, isAtomAndNotText } - -/* (c) David Pollak 2007 WorldWide Conferencing, LLC */ - -object Xhtml -{ - /** - * Convenience function: same as toXhtml(node, false, false) - * - * @param node the node - */ - def toXhtml(node: Node): String = sbToString(sb => toXhtml(x = node, sb = sb)) - - /** - * Convenience function: amounts to calling toXhtml(node) on each - * node in the sequence. - * - * @param nodeSeq the node sequence - */ - def toXhtml(nodeSeq: NodeSeq): String = sbToString(sb => sequenceToXML(nodeSeq: Seq[Node], sb = sb)) - - /** Elements which we believe are safe to minimize if minimizeTags is true. - * See http://www.w3.org/TR/xhtml1/guidelines.html#C_3 - */ - private val minimizableElements = - List("base", "meta", "link", "hr", "br", "param", "img", "area", "input", "col") - - def toXhtml( - x: Node, - pscope: NamespaceBinding = TopScope, - sb: StringBuilder = new StringBuilder, - stripComments: Boolean = false, - decodeEntities: Boolean = false, - preserveWhitespace: Boolean = false, - minimizeTags: Boolean = true): Unit = - { - def decode(er: EntityRef) = XhtmlEntities.entMap.get(er.entityName) match { - case Some(chr) if chr.toInt >= 128 => sb.append(chr) - case _ => er.buildString(sb) - } - def shortForm = - minimizeTags && - (x.child == null || x.child.length == 0) && - (minimizableElements contains x.label) - - x match { - case c: Comment => if (!stripComments) c buildString sb - case er: EntityRef if decodeEntities => decode(er) - case x: SpecialNode => x buildString sb - case g: Group => - g.nodes foreach { toXhtml(_, x.scope, sb, stripComments, decodeEntities, preserveWhitespace, minimizeTags) } - - case _ => - sb.append('<') - x.nameToString(sb) - if (x.attributes ne null) x.attributes.buildString(sb) - x.scope.buildString(sb, pscope) - - if (shortForm) sb.append(" />") - else { - sb.append('>') - sequenceToXML(x.child, x.scope, sb, stripComments, decodeEntities, preserveWhitespace, minimizeTags) - sb.append("</") - x.nameToString(sb) - sb.append('>') - } - } - } - - /** - * Amounts to calling toXhtml(node, ...) with the given parameters on each node. - */ - def sequenceToXML( - children: Seq[Node], - pscope: NamespaceBinding = TopScope, - sb: StringBuilder = new StringBuilder, - stripComments: Boolean = false, - decodeEntities: Boolean = false, - preserveWhitespace: Boolean = false, - minimizeTags: Boolean = true): Unit = - { - if (children.isEmpty) - return - - val doSpaces = children forall isAtomAndNotText // interleave spaces - for (c <- children.take(children.length - 1)) { - toXhtml(c, pscope, sb, stripComments, decodeEntities, preserveWhitespace, minimizeTags) - if (doSpaces) sb append ' ' - } - toXhtml(children.last, pscope, sb, stripComments, decodeEntities, preserveWhitespace, minimizeTags) - } -} diff --git a/src/library/scala/xml/dtd/ContentModel.scala b/src/library/scala/xml/dtd/ContentModel.scala deleted file mode 100644 index abc71f55bd..0000000000 --- a/src/library/scala/xml/dtd/ContentModel.scala +++ /dev/null @@ -1,120 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - - -package scala.xml -package dtd - -import scala.util.regexp.WordExp -import scala.util.automata._ -import scala.xml.Utility.sbToString -import PartialFunction._ - -object ContentModel extends WordExp { - type _labelT = ElemName - type _regexpT = RegExp - - object Translator extends WordBerrySethi { - override val lang: ContentModel.this.type = ContentModel.this - } - - case class ElemName(name: String) extends Label { - override def toString() = """ElemName("%s")""" format name - } - - def isMixed(cm: ContentModel) = cond(cm) { case _: MIXED => true } - def containsText(cm: ContentModel) = (cm == PCDATA) || isMixed(cm) - def parse(s: String): ContentModel = ContentModelParser.parse(s) - - def getLabels(r: RegExp): Set[String] = { - def traverse(r: RegExp): Set[String] = r match { // !!! check for match translation problem - case Letter(ElemName(name)) => Set(name) - case Star( x @ _ ) => traverse( x ) // bug if x@_* - case Sequ( xs @ _* ) => Set(xs flatMap traverse: _*) - case Alt( xs @ _* ) => Set(xs flatMap traverse: _*) - } - - traverse(r) - } - - def buildString(r: RegExp): String = sbToString(buildString(r, _)) - - /* precond: rs.length >= 1 */ - private def buildString(rs: Seq[RegExp], sb: StringBuilder, sep: Char) { - buildString(rs.head, sb) - for (z <- rs.tail) { - sb append sep - buildString(z, sb) - } - } - - def buildString(c: ContentModel, sb: StringBuilder): StringBuilder = c match { - case ANY => sb append "ANY" - case EMPTY => sb append "EMPTY" - case PCDATA => sb append "(#PCDATA)" - case ELEMENTS(_) | MIXED(_) => c buildString sb - } - - def buildString(r: RegExp, sb: StringBuilder): StringBuilder = - r match { // !!! check for match translation problem - case Eps => - sb - case Sequ(rs @ _*) => - sb.append( '(' ); buildString(rs, sb, ','); sb.append( ')' ) - case Alt(rs @ _*) => - sb.append( '(' ); buildString(rs, sb, '|'); sb.append( ')' ) - case Star(r: RegExp) => - sb.append( '(' ); buildString(r, sb); sb.append( ")*" ) - case Letter(ElemName(name)) => - sb.append(name) - } - -} - -sealed abstract class ContentModel -{ - override def toString(): String = sbToString(buildString) - def buildString(sb: StringBuilder): StringBuilder -} - -case object PCDATA extends ContentModel { - override def buildString(sb: StringBuilder): StringBuilder = sb.append("(#PCDATA)") -} -case object EMPTY extends ContentModel { - override def buildString(sb: StringBuilder): StringBuilder = sb.append("EMPTY") -} -case object ANY extends ContentModel { - override def buildString(sb: StringBuilder): StringBuilder = sb.append("ANY") -} -sealed abstract class DFAContentModel extends ContentModel { - import ContentModel.{ ElemName, Translator } - def r: ContentModel.RegExp - - lazy val dfa: DetWordAutom[ElemName] = { - val nfa = Translator.automatonFrom(r, 1) - new SubsetConstruction(nfa).determinize - } -} - -case class MIXED(r: ContentModel.RegExp) extends DFAContentModel { - import ContentModel.{ Alt, RegExp } - - override def buildString(sb: StringBuilder): StringBuilder = { - val newAlt = r match { case Alt(rs @ _*) => Alt(rs drop 1: _*) } - - sb append "(#PCDATA|" - ContentModel.buildString(newAlt: RegExp, sb) - sb append ")*" - } -} - -case class ELEMENTS(r: ContentModel.RegExp) extends DFAContentModel { - override def buildString(sb: StringBuilder): StringBuilder = - ContentModel.buildString(r, sb) -} diff --git a/src/library/scala/xml/dtd/ContentModelParser.scala b/src/library/scala/xml/dtd/ContentModelParser.scala deleted file mode 100644 index ace02193da..0000000000 --- a/src/library/scala/xml/dtd/ContentModelParser.scala +++ /dev/null @@ -1,128 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://www.scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala.xml -package dtd - -/** Parser for regexps (content models in DTD element declarations) */ - -object ContentModelParser extends Scanner { // a bit too permissive concerning #PCDATA - import ContentModel._ - - /** parses the argument to a regexp */ - def parse(s: String): ContentModel = { initScanner(s); contentspec } - - def accept(tok: Int) = { - if (token != tok) { - if ((tok == STAR) && (token == END)) // common mistake - scala.sys.error("in DTDs, \n"+ - "mixed content models must be like (#PCDATA|Name|Name|...)*"); - else - scala.sys.error("expected "+token2string(tok)+ - ", got unexpected token:"+token2string(token)); - } - nextToken - } - - // s [ '+' | '*' | '?' ] - def maybeSuffix(s: RegExp) = token match { - case STAR => nextToken; Star(s) - case PLUS => nextToken; Sequ(s, Star(s)) - case OPT => nextToken; Alt(Eps, s) - case _ => s - } - - // contentspec ::= EMPTY | ANY | (#PCDATA) | "(#PCDATA|"regexp) - - def contentspec: ContentModel = token match { - - case NAME => value match { - case "ANY" => ANY - case "EMPTY" => EMPTY - case _ => scala.sys.error("expected ANY, EMPTY or '(' instead of " + value ); - } - case LPAREN => - - nextToken; - sOpt; - if (token != TOKEN_PCDATA) - ELEMENTS(regexp); - else { - nextToken; - token match { - case RPAREN => - PCDATA - case CHOICE => - val res = MIXED(choiceRest(Eps)); - sOpt; - accept( RPAREN ); - accept( STAR ); - res - case _ => - scala.sys.error("unexpected token:" + token2string(token) ); - } - } - - case _ => - scala.sys.error("unexpected token:" + token2string(token) ); - } - // sopt ::= S? - def sOpt() = if( token == S ) nextToken; - - // (' S? mixed ::= '#PCDATA' S? ')' - // | '#PCDATA' (S? '|' S? atom)* S? ')*' - - // '(' S? regexp ::= cp S? [seqRest|choiceRest] ')' [ '+' | '*' | '?' ] - def regexp: RegExp = { - val p = particle; - sOpt; - maybeSuffix(token match { - case RPAREN => nextToken; p - case CHOICE => val q = choiceRest( p );accept( RPAREN ); q - case COMMA => val q = seqRest( p ); accept( RPAREN ); q - }) - } - - // seqRest ::= (',' S? cp S?)+ - def seqRest(p: RegExp) = { - var k = List(p); - while( token == COMMA ) { - nextToken; - sOpt; - k = particle::k; - sOpt; - } - Sequ( k.reverse:_* ) - } - - // choiceRest ::= ('|' S? cp S?)+ - def choiceRest( p:RegExp ) = { - var k = List( p ); - while( token == CHOICE ) { - nextToken; - sOpt; - k = particle::k; - sOpt; - } - Alt( k.reverse:_* ) - } - - // particle ::= '(' S? regexp - // | name [ '+' | '*' | '?' ] - def particle = token match { - case LPAREN => nextToken; sOpt; regexp; - case NAME => val a = Letter(ElemName(value)); nextToken; maybeSuffix(a) - case _ => scala.sys.error("expected '(' or Name, got:"+token2string(token)); - } - - // atom ::= name - def atom = token match { - case NAME => val a = Letter(ElemName(value)); nextToken; a - case _ => scala.sys.error("expected Name, got:"+token2string(token)); - } -} diff --git a/src/library/scala/xml/dtd/DTD.scala b/src/library/scala/xml/dtd/DTD.scala deleted file mode 100644 index 1f8af3b59e..0000000000 --- a/src/library/scala/xml/dtd/DTD.scala +++ /dev/null @@ -1,34 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - -package scala.xml -package dtd - -import scala.collection.mutable - -/** A document type declaration. - * - * @author Burak Emir - */ -abstract class DTD { - var externalID: ExternalID = null - var decls: List[Decl] = Nil - def notations: Seq[NotationDecl] = Nil - def unparsedEntities: Seq[EntityDecl] = Nil - - var elem: mutable.Map[String, ElemDecl] = new mutable.HashMap[String, ElemDecl]() - var attr: mutable.Map[String, AttListDecl] = new mutable.HashMap[String, AttListDecl]() - var ent: mutable.Map[String, EntityDecl] = new mutable.HashMap[String, EntityDecl]() - - override def toString() = - "DTD [\n%s%s]".format( - Option(externalID) getOrElse "", - decls.mkString("", "\n", "\n") - ) -} diff --git a/src/library/scala/xml/dtd/Decl.scala b/src/library/scala/xml/dtd/Decl.scala deleted file mode 100644 index dc4cb93ddf..0000000000 --- a/src/library/scala/xml/dtd/Decl.scala +++ /dev/null @@ -1,156 +0,0 @@ -/* __ *\ - ** ________ ___ / / ___ Scala API ** - ** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** - ** __\ \/ /__/ __ |/ /__/ __ | http://www.scala-lang.org/ ** - ** /____/\___/_/ |_/____/_/ | | ** - ** |/ ** - \* */ - -package scala.xml -package dtd - -import Utility.sbToString - -abstract class Decl - -abstract class MarkupDecl extends Decl { - def buildString(sb: StringBuilder): StringBuilder -} - -/** an element declaration - */ -case class ElemDecl(name: String, contentModel: ContentModel) -extends MarkupDecl { - override def buildString(sb: StringBuilder): StringBuilder = { - sb append "<!ELEMENT " append name append ' ' - - ContentModel.buildString(contentModel, sb) - sb append '>' - } -} - -case class AttListDecl(name: String, attrs:List[AttrDecl]) -extends MarkupDecl { - override def buildString(sb: StringBuilder): StringBuilder = { - sb append "<!ATTLIST " append name append '\n' append attrs.mkString("","\n",">") - } -} - -/** an attribute declaration. at this point, the tpe is a string. Future - * versions might provide a way to access the attribute types more - * directly. - */ -case class AttrDecl(name: String, tpe: String, default: DefaultDecl) { - override def toString(): String = sbToString(buildString) - - def buildString(sb: StringBuilder): StringBuilder = { - sb append " " append name append ' ' append tpe append ' ' - default buildString sb - } - -} - -/** an entity declaration */ -abstract class EntityDecl extends MarkupDecl - -/** a parsed general entity declaration */ -case class ParsedEntityDecl(name: String, entdef: EntityDef) extends EntityDecl { - override def buildString(sb: StringBuilder): StringBuilder = { - sb append "<!ENTITY " append name append ' ' - entdef buildString sb append '>' - } -} - -/** a parameter entity declaration */ -case class ParameterEntityDecl(name: String, entdef: EntityDef) extends EntityDecl { - override def buildString(sb: StringBuilder): StringBuilder = { - sb append "<!ENTITY % " append name append ' ' - entdef buildString sb append '>' - } -} - -/** an unparsed entity declaration */ -case class UnparsedEntityDecl( name:String, extID:ExternalID, notation:String ) extends EntityDecl { - override def buildString(sb: StringBuilder): StringBuilder = { - sb append "<!ENTITY " append name append ' ' - extID buildString sb append " NDATA " append notation append '>' - } -} -/** a notation declaration */ -case class NotationDecl( name:String, extID:ExternalID ) extends MarkupDecl { - override def buildString(sb: StringBuilder): StringBuilder = { - sb append "<!NOTATION " append name append ' ' - extID buildString sb - } -} - -abstract class EntityDef { - def buildString(sb: StringBuilder): StringBuilder -} - -case class IntDef(value:String) extends EntityDef { - private def validateValue() { - var tmp = value - var ix = tmp indexOf '%' - while (ix != -1) { - val iz = tmp.indexOf(';', ix) - if(iz == -1 && iz == ix + 1) - throw new IllegalArgumentException("no % allowed in entity value, except for parameter-entity-references") - else { - val n = tmp.substring(ix, iz) - - if (!Utility.isName(n)) - throw new IllegalArgumentException("internal entity def: \""+n+"\" must be an XML Name") - - tmp = tmp.substring(iz+1, tmp.length) - ix = tmp indexOf '%' - } - } - } - validateValue() - - override def buildString(sb: StringBuilder): StringBuilder = - Utility.appendQuoted(value, sb) - -} - -case class ExtDef(extID:ExternalID) extends EntityDef { - override def buildString(sb: StringBuilder): StringBuilder = - extID buildString sb -} - - -/** a parsed entity reference */ -case class PEReference(ent:String) extends MarkupDecl { - if( !Utility.isName( ent )) - throw new IllegalArgumentException("ent must be an XML Name"); - - override def buildString(sb: StringBuilder): StringBuilder = - sb append '%' append ent append ';' -} - - -// default declarations for attributes - -abstract class DefaultDecl { - override def toString(): String - def buildString(sb: StringBuilder): StringBuilder -} - -case object REQUIRED extends DefaultDecl { - override def toString(): String = "#REQUIRED" - override def buildString(sb: StringBuilder) = sb append "#REQUIRED" -} - -case object IMPLIED extends DefaultDecl { - override def toString(): String = "#IMPLIED" - override def buildString(sb: StringBuilder) = sb append "#IMPLIED" -} - -case class DEFAULT(fixed: Boolean, attValue: String) extends DefaultDecl { - override def toString(): String = sbToString(buildString) - override def buildString(sb: StringBuilder): StringBuilder = { - if (fixed) sb append "#FIXED " - Utility.appendEscapedQuoted(attValue, sb) - } -} diff --git a/src/library/scala/xml/dtd/DocType.scala b/src/library/scala/xml/dtd/DocType.scala deleted file mode 100644 index 79f8f9fe8b..0000000000 --- a/src/library/scala/xml/dtd/DocType.scala +++ /dev/null @@ -1,34 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - -package scala.xml -package dtd - -/** An XML node for document type declaration. - * - * @author Burak Emir - * - * @param name name of this DOCTYPE - * @param extID None, or Some(external ID of this doctype) - * @param intSubset sequence of internal subset declarations - */ -case class DocType(name: String, extID: ExternalID, intSubset: Seq[dtd.Decl]) -{ - if (!Utility.isName(name)) - throw new IllegalArgumentException(name+" must be an XML Name") - - /** returns "<!DOCTYPE + name + extID? + ("["+intSubSet+"]")? >" */ - final override def toString() = { - def intString = - if (intSubset.isEmpty) "" - else intSubset.mkString("[", "", "]") - - """<!DOCTYPE %s %s%s>""".format(name, extID.toString, intString) - } -} diff --git a/src/library/scala/xml/dtd/ElementValidator.scala b/src/library/scala/xml/dtd/ElementValidator.scala deleted file mode 100644 index bfc85f48a9..0000000000 --- a/src/library/scala/xml/dtd/ElementValidator.scala +++ /dev/null @@ -1,129 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://www.scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - - -package scala.xml -package dtd - -import PartialFunction._ -import ContentModel.ElemName -import MakeValidationException._ // @todo other exceptions -import scala.util.automata._ -import scala.collection.mutable - -/** validate children and/or attributes of an element - * exceptions are created but not thrown. - */ -class ElementValidator() extends Function1[Node,Boolean] { - - private var exc: List[ValidationException] = Nil - - protected var contentModel: ContentModel = _ - protected var dfa: DetWordAutom[ElemName] = _ - protected var adecls: List[AttrDecl] = _ - - /** set content model, enabling element validation */ - def setContentModel(cm: ContentModel) = { - contentModel = cm - cm match { - case ELEMENTS(r) => - val nfa = ContentModel.Translator.automatonFrom(r, 1) - dfa = new SubsetConstruction(nfa).determinize - case _ => - dfa = null - } - } - - def getContentModel = contentModel - - /** set meta data, enabling attribute validation */ - def setMetaData(adecls: List[AttrDecl]) { this.adecls = adecls } - - def getIterable(nodes: Seq[Node], skipPCDATA: Boolean): Iterable[ElemName] = { - def isAllWhitespace(a: Atom[_]) = cond(a.data) { case s: String if s.trim == "" => true } - - nodes.filter { - case y: SpecialNode => y match { - case a: Atom[_] if isAllWhitespace(a) => false // always skip all-whitespace nodes - case _ => !skipPCDATA - } - case x => x.namespace eq null - } . map (x => ElemName(x.label)) - } - - /** check attributes, return true if md corresponds to attribute declarations in adecls. - */ - def check(md: MetaData): Boolean = { - val len: Int = exc.length - var ok = new mutable.BitSet(adecls.length) - - for (attr <- md) { - def attrStr = attr.value.toString - def find(Key: String): Option[AttrDecl] = { - adecls.zipWithIndex find { - case (a @ AttrDecl(Key, _, _), j) => ok += j ; return Some(a) - case _ => false - } - None - } - - find(attr.key) match { - case None => - exc ::= fromUndefinedAttribute(attr.key) - - case Some(AttrDecl(_, tpe, DEFAULT(true, fixedValue))) if attrStr != fixedValue => - exc ::= fromFixedAttribute(attr.key, fixedValue, attrStr) - - case _ => - } - } - - adecls.zipWithIndex foreach { - case (AttrDecl(key, tpe, REQUIRED), j) if !ok(j) => exc ::= fromMissingAttribute(key, tpe) - case _ => - } - - exc.length == len //- true if no new exception - } - - /** check children, return true if conform to content model - * @note contentModel != null - */ - def check(nodes: Seq[Node]): Boolean = contentModel match { - case ANY => true - case EMPTY => getIterable(nodes, false).isEmpty - case PCDATA => getIterable(nodes, true).isEmpty - case MIXED(ContentModel.Alt(branches @ _*)) => // @todo - val j = exc.length - def find(Key: String): Boolean = - branches exists { case ContentModel.Letter(ElemName(Key)) => true ; case _ => false } - - getIterable(nodes, true) map (_.name) filterNot find foreach { - exc ::= MakeValidationException fromUndefinedElement _ - } - (exc.length == j) // - true if no new exception - - case _: ELEMENTS => - dfa isFinal { - getIterable(nodes, false).foldLeft(0) { (q, e) => - (dfa delta q).getOrElse(e, throw ValidationException("element %s not allowed here" format e)) - } - } - case _ => false - } - - /** applies various validations - accumulates error messages in exc - * @todo fail on first error, ignore other errors (rearranging conditions) - */ - def apply(n: Node): Boolean = - //- ? check children - ((contentModel == null) || check(n.child)) && - //- ? check attributes - ((adecls == null) || check(n.attributes)) -} diff --git a/src/library/scala/xml/dtd/ExternalID.scala b/src/library/scala/xml/dtd/ExternalID.scala deleted file mode 100644 index 7a7463569e..0000000000 --- a/src/library/scala/xml/dtd/ExternalID.scala +++ /dev/null @@ -1,75 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://www.scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - -package scala.xml -package dtd - -/** an ExternalIDs - either PublicID or SystemID - * - * @author Burak Emir - */ -abstract class ExternalID extends parsing.TokenTests -{ - def quoted(s: String) = { - val c = if (s contains '"') '\'' else '"' - c + s + c - } - - // public != null: PUBLIC " " publicLiteral " " [systemLiteral] - // public == null: SYSTEM " " systemLiteral - override def toString(): String = { - lazy val quotedSystemLiteral = quoted(systemId) - lazy val quotedPublicLiteral = quoted(publicId) - - if (publicId == null) "SYSTEM " + quotedSystemLiteral - else "PUBLIC " + quotedPublicLiteral + - (if (systemId == null) "" else " " + quotedSystemLiteral) - } - def buildString(sb: StringBuilder): StringBuilder = - sb.append(this.toString()) - - def systemId: String - def publicId: String -} - -/** a system identifier - * - * @author Burak Emir - * @param systemId the system identifier literal - */ -case class SystemID(systemId: String) extends ExternalID { - val publicId = null - - if (!checkSysID(systemId)) - throw new IllegalArgumentException("can't use both \" and ' in systemId") -} - - -/** a public identifier (see http://www.w3.org/QA/2002/04/valid-dtd-list.html). - * - * @author Burak Emir - * @param publicId the public identifier literal - * @param systemId (can be null for notation pubIDs) the system identifier literal - */ -case class PublicID(publicId: String, systemId: String) extends ExternalID { - if (!checkPubID(publicId)) - throw new IllegalArgumentException("publicId must consist of PubidChars") - - if (systemId != null && !checkSysID(systemId)) - throw new IllegalArgumentException("can't use both \" and ' in systemId") - - /** the constant "#PI" */ - def label = "#PI" - - /** always empty */ - def attribute = Node.NoAttributes - - /** always empty */ - def child = Nil -} diff --git a/src/library/scala/xml/dtd/Scanner.scala b/src/library/scala/xml/dtd/Scanner.scala deleted file mode 100644 index 9b64cc61e2..0000000000 --- a/src/library/scala/xml/dtd/Scanner.scala +++ /dev/null @@ -1,78 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - -package scala.xml -package dtd - -/** Scanner for regexps (content models in DTD element declarations) - * todo: cleanup - */ -class Scanner extends Tokens with parsing.TokenTests { - - final val ENDCH = '\u0000' - - var token:Int = END - var value:String = _ - - private var it: Iterator[Char] = null - private var c: Char = 'z' - - /** initializes the scanner on input s */ - final def initScanner(s: String) { - value = "" - it = (s).iterator - token = 1+END - next - nextToken - } - - /** scans the next token */ - final def nextToken() { - if (token != END) token = readToken - } - - // todo: see XML specification... probably isLetter,isDigit is fine - final def isIdentChar = ( ('a' <= c && c <= 'z') - || ('A' <= c && c <= 'Z')); - - final def next() = if (it.hasNext) c = it.next else c = ENDCH - - final def acc(d: Char) { - if (c == d) next else scala.sys.error("expected '"+d+"' found '"+c+"' !"); - } - - final def accS(ds: Seq[Char]) { ds foreach acc } - - final def readToken: Int = - if (isSpace(c)) { - while (isSpace(c)) c = it.next - S - } else c match { - case '(' => next; LPAREN - case ')' => next; RPAREN - case ',' => next; COMMA - case '*' => next; STAR - case '+' => next; PLUS - case '?' => next; OPT - case '|' => next; CHOICE - case '#' => next; accS( "PCDATA" ); TOKEN_PCDATA - case ENDCH => END - case _ => - if (isNameStart(c)) name; // NAME - else scala.sys.error("unexpected character:" + c) - } - - final def name = { - val sb = new StringBuilder() - do { sb.append(c); next } while (isNameChar(c)); - value = sb.toString() - NAME - } - -} diff --git a/src/library/scala/xml/dtd/Tokens.scala b/src/library/scala/xml/dtd/Tokens.scala deleted file mode 100644 index eaffba99a4..0000000000 --- a/src/library/scala/xml/dtd/Tokens.scala +++ /dev/null @@ -1,44 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://www.scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - - -package scala.xml -package dtd - - -class Tokens { - - // Tokens - - final val TOKEN_PCDATA = 0 - final val NAME = 1 - final val LPAREN = 3 - final val RPAREN = 4 - final val COMMA = 5 - final val STAR = 6 - final val PLUS = 7 - final val OPT = 8 - final val CHOICE = 9 - final val END = 10 - final val S = 13 - - final def token2string(i: Int): String = i match { - case 0 => "#PCDATA" - case 1 => "NAME" - case 3 => "(" - case 4 => ")" - case 5 => "," - case 6 => "*" - case 7 => "+" - case 8 => "?" - case 9 => "|" - case 10 => "END" - case 13 => " " - } -} diff --git a/src/library/scala/xml/dtd/ValidationException.scala b/src/library/scala/xml/dtd/ValidationException.scala deleted file mode 100644 index 243db69ab7..0000000000 --- a/src/library/scala/xml/dtd/ValidationException.scala +++ /dev/null @@ -1,43 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://www.scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - - -package scala.xml -package dtd - - -case class ValidationException(e: String) extends Exception(e) - -/** - * @author Burak Emir - */ -object MakeValidationException { - def fromFixedAttribute(k: String, value: String, actual: String) = - ValidationException("value of attribute " + k + " FIXED to \""+ - value+"\", but document tries \""+actual+"\"") - - def fromNonEmptyElement() = - new ValidationException("element should be *empty*") - - def fromUndefinedElement(label: String) = - new ValidationException("element \""+ label +"\" not allowed here") - - def fromUndefinedAttribute(key: String) = - new ValidationException("attribute " + key +" not allowed here") - - def fromMissingAttribute(allKeys: Set[String]) = { - val sb = new StringBuilder("missing value for REQUIRED attribute") - if (allKeys.size > 1) sb.append('s'); - allKeys foreach (k => sb append "'%s'".format(k)) - new ValidationException(sb.toString()) - } - - def fromMissingAttribute(key: String, tpe: String) = - new ValidationException("missing value for REQUIRED attribute %s of type %s".format(key, tpe)) -} diff --git a/src/library/scala/xml/factory/Binder.scala b/src/library/scala/xml/factory/Binder.scala deleted file mode 100755 index bad4a4ea09..0000000000 --- a/src/library/scala/xml/factory/Binder.scala +++ /dev/null @@ -1,60 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - - -package scala.xml -package factory - -import parsing.ValidatingMarkupHandler - -/** - * @author Burak Emir - */ -abstract class Binder(val preserveWS: Boolean) extends ValidatingMarkupHandler { - - var result: NodeBuffer = new NodeBuffer() - - def reportSyntaxError(pos:Int, str:String) = {} - - final def procInstr(pos: Int, target: String, txt: String) = - ProcInstr(target, txt) - - final def comment(pos: Int, txt: String) = - Comment(txt) - - final def entityRef(pos: Int, n: String) = - EntityRef(n) - - final def text(pos: Int, txt: String) = - Text(txt) - - final def traverse(n:Node): Unit = n match { - case x:ProcInstr => - result &+ procInstr(0, x.target, x.text) - case x:Comment => - result &+ comment(0, x.text) - case x:Text => - result &+ text(0, x.data) - case x:EntityRef => - result &+ entityRef(0, x.entityName) - case x:Elem => - elemStart(0, x.prefix, x.label, x.attributes, x.scope) - val old = result - result = new NodeBuffer() - for (m <- x.child) traverse(m) - result = old &+ elem(0, x.prefix, x.label, x.attributes, x.scope, x.minimizeEmpty, NodeSeq.fromSeq(result)).toList; - elemEnd(0, x.prefix, x.label) - } - - final def validate(n: Node): Node = { - this.rootLabel = n.label - traverse(n) - result(0) - } -} diff --git a/src/library/scala/xml/factory/LoggedNodeFactory.scala b/src/library/scala/xml/factory/LoggedNodeFactory.scala deleted file mode 100644 index cac61acc39..0000000000 --- a/src/library/scala/xml/factory/LoggedNodeFactory.scala +++ /dev/null @@ -1,85 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala.xml -package factory - -/** This class logs what the nodefactory is actually doing. - * If you want to see what happens during loading, use it like this: -{{{ -object testLogged extends App { - val x = new scala.xml.parsing.NoBindingFactoryAdapter - with scala.xml.factory.LoggedNodeFactory[scala.xml.Elem] - with scala.util.logging.ConsoleLogger - - Console.println("Start") - val doc = x.load(new java.net.URL("http://example.com/file.xml")) - Console.println("End") - Console.println(doc) -} -}}} - * - * @author Burak Emir - * @version 1.0 - */ -trait LoggedNodeFactory[A <: Node] extends NodeFactory[A] with scala.util.logging.Logged { - // configuration values - val logNode = true - val logText = false - val logComment = false - val logProcInstr = false - - final val NONE = 0 - final val CACHE = 1 - final val FULL = 2 - /** 0 = no logging, 1 = cache hits, 2 = detail */ - val logCompressLevel = 1 - - // methods of NodeFactory - - /** logged version of makeNode method */ - override def makeNode(pre: String, label: String, attrSeq: MetaData, - scope: NamespaceBinding, children: Seq[Node]): A = { - if (logNode) - log("[makeNode for "+label+"]"); - - val hash = Utility.hashCode(pre, label, attrSeq.##, scope.##, children) - - /* - if(logCompressLevel >= FULL) { - log("[hashcode total:"+hash); - log(" elem name "+uname+" hash "+ ? )); - log(" attrs "+attrSeq+" hash "+attrSeq.hashCode()); - log(" children :"+children+" hash "+children.hashCode()); - } - */ - if (!cache.get( hash ).isEmpty && (logCompressLevel >= CACHE)) - log("[cache hit !]"); - - super.makeNode(pre, label, attrSeq, scope, children) - } - - override def makeText(s: String) = { - if (logText) - log("[makeText:\""+s+"\"]"); - super.makeText(s) - } - - override def makeComment(s: String): Seq[Comment] = { - if (logComment) - log("[makeComment:\""+s+"\"]"); - super.makeComment(s) - } - - override def makeProcInstr(t: String, s: String): Seq[ProcInstr] = { - if (logProcInstr) - log("[makeProcInstr:\""+t+" "+ s+"\"]"); - super.makeProcInstr(t, s) - } - -} diff --git a/src/library/scala/xml/factory/NodeFactory.scala b/src/library/scala/xml/factory/NodeFactory.scala deleted file mode 100644 index 28a1b6fff4..0000000000 --- a/src/library/scala/xml/factory/NodeFactory.scala +++ /dev/null @@ -1,60 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - -package scala.xml -package factory - -import parsing.{ FactoryAdapter, NoBindingFactoryAdapter } -import java.io.{ InputStream, Reader, StringReader, File, FileDescriptor, FileInputStream } - -trait NodeFactory[A <: Node] { - val ignoreComments = false - val ignoreProcInstr = false - - /* default behaviour is to use hash-consing */ - val cache = new scala.collection.mutable.HashMap[Int, List[A]] - - protected def create(pre: String, name: String, attrs: MetaData, scope: NamespaceBinding, children:Seq[Node]): A - - protected def construct(hash: Int, old:List[A], pre: String, name: String, attrSeq:MetaData, scope: NamespaceBinding, children:Seq[Node]): A = { - val el = create(pre, name, attrSeq, scope, children) - cache.update(hash, el :: old) - el - } - - def eqElements(ch1: Seq[Node], ch2: Seq[Node]): Boolean = - ch1.view.zipAll(ch2.view, null, null) forall { case (x,y) => x eq y } - - def nodeEquals(n: Node, pre: String, name: String, attrSeq:MetaData, scope: NamespaceBinding, children: Seq[Node]) = - n.prefix == pre && - n.label == name && - n.attributes == attrSeq && - // scope? - eqElements(n.child, children) - - def makeNode(pre: String, name: String, attrSeq: MetaData, scope: NamespaceBinding, children: Seq[Node]): A = { - val hash = Utility.hashCode( pre, name, attrSeq.##, scope.##, children) - def cons(old: List[A]) = construct(hash, old, pre, name, attrSeq, scope, children) - - (cache get hash) match { - case Some(list) => // find structurally equal - list.find(nodeEquals(_, pre, name, attrSeq, scope, children)) match { - case Some(x) => x - case _ => cons(list) - } - case None => cons(Nil) - } - } - - def makeText(s: String) = Text(s) - def makeComment(s: String): Seq[Comment] = - if (ignoreComments) Nil else List(Comment(s)) - def makeProcInstr(t: String, s: String): Seq[ProcInstr] = - if (ignoreProcInstr) Nil else List(ProcInstr(t, s)) -} diff --git a/src/library/scala/xml/factory/XMLLoader.scala b/src/library/scala/xml/factory/XMLLoader.scala deleted file mode 100644 index 72e4c51b11..0000000000 --- a/src/library/scala/xml/factory/XMLLoader.scala +++ /dev/null @@ -1,60 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - -package scala.xml -package factory - -import javax.xml.parsers.SAXParserFactory -import parsing.{ FactoryAdapter, NoBindingFactoryAdapter } -import java.io.{ InputStream, Reader, StringReader, File, FileDescriptor, FileInputStream } -import java.net.URL - -/** Presents collection of XML loading methods which use the parser - * created by "def parser". - */ -trait XMLLoader[T <: Node] -{ - import scala.xml.Source._ - def adapter: FactoryAdapter = new NoBindingFactoryAdapter() - - /* Override this to use a different SAXParser. */ - def parser: SAXParser = { - val f = SAXParserFactory.newInstance() - f.setNamespaceAware(false) - f.newSAXParser() - } - - /** Loads XML from the given InputSource, using the supplied parser. - * The methods available in scala.xml.XML use the XML parser in the JDK. - */ - def loadXML(source: InputSource, parser: SAXParser): T = { - val newAdapter = adapter - - newAdapter.scopeStack push TopScope - parser.parse(source, newAdapter) - newAdapter.scopeStack.pop - - newAdapter.rootElem.asInstanceOf[T] - } - - /** Loads XML from the given file, file descriptor, or filename. */ - def loadFile(file: File): T = loadXML(fromFile(file), parser) - def loadFile(fd: FileDescriptor): T = loadXML(fromFile(fd), parser) - def loadFile(name: String): T = loadXML(fromFile(name), parser) - - /** loads XML from given InputStream, Reader, sysID, InputSource, or URL. */ - def load(is: InputStream): T = loadXML(fromInputStream(is), parser) - def load(reader: Reader): T = loadXML(fromReader(reader), parser) - def load(sysID: String): T = loadXML(fromSysId(sysID), parser) - def load(source: InputSource): T = loadXML(source, parser) - def load(url: URL): T = loadXML(fromInputStream(url.openStream()), parser) - - /** Loads XML from the given String. */ - def loadString(string: String): T = loadXML(fromString(string), parser) -} diff --git a/src/library/scala/xml/include/CircularIncludeException.scala b/src/library/scala/xml/include/CircularIncludeException.scala deleted file mode 100644 index 5e74967d54..0000000000 --- a/src/library/scala/xml/include/CircularIncludeException.scala +++ /dev/null @@ -1,24 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala.xml -package include - -/** - * A `CircularIncludeException` is thrown when an included document attempts - * to include itself or one of its ancestor documents. - */ -class CircularIncludeException(message: String) extends XIncludeException { - - /** - * Constructs a `CircularIncludeException` with `'''null'''`. - * as its error detail message. - */ - def this() = this(null) - -} diff --git a/src/library/scala/xml/include/UnavailableResourceException.scala b/src/library/scala/xml/include/UnavailableResourceException.scala deleted file mode 100644 index f00cc58699..0000000000 --- a/src/library/scala/xml/include/UnavailableResourceException.scala +++ /dev/null @@ -1,19 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala.xml -package include - -/** - * An `UnavailableResourceException` is thrown when an included document - * cannot be found or loaded. - */ -class UnavailableResourceException(message: String) -extends XIncludeException(message) { - def this() = this(null) -} diff --git a/src/library/scala/xml/include/XIncludeException.scala b/src/library/scala/xml/include/XIncludeException.scala deleted file mode 100644 index 84033f853f..0000000000 --- a/src/library/scala/xml/include/XIncludeException.scala +++ /dev/null @@ -1,57 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala.xml -package include - -/** - * `XIncludeException` is the generic superclass for all checked exceptions - * that may be thrown as a result of a violation of XInclude's rules. - * - * Constructs an `XIncludeException` with the specified detail message. - * The error message string `message` can later be retrieved by the - * `{@link java.lang.Throwable#getMessage}` - * method of class `java.lang.Throwable`. - * - * @param message the detail message. - */ -class XIncludeException(message: String) extends Exception(message) { - - /** - * uses `'''null'''` as its error detail message. - */ - def this() = this(null) - - private var rootCause: Throwable = null - - /** - * When an `IOException`, `MalformedURLException` or other generic - * exception is thrown while processing an XML document for XIncludes, - * it is customarily replaced by some form of `XIncludeException`. - * This method allows you to store the original exception. - * - * @param nestedException the underlying exception which - * caused the XIncludeException to be thrown - */ - def setRootCause(nestedException: Throwable ) { - this.rootCause = nestedException - } - - /** - * When an `IOException`, `MalformedURLException` or other generic - * exception is thrown while processing an XML document for XIncludes, - * it is customarily replaced by some form of `XIncludeException`. - * This method allows you to retrieve the original exception. - * It returns null if no such exception caused this `XIncludeException`. - * - * @return Throwable the underlying exception which caused the - * `XIncludeException` to be thrown - */ - def getRootCause(): Throwable = this.rootCause - -} diff --git a/src/library/scala/xml/include/sax/EncodingHeuristics.scala b/src/library/scala/xml/include/sax/EncodingHeuristics.scala deleted file mode 100644 index 1340689cae..0000000000 --- a/src/library/scala/xml/include/sax/EncodingHeuristics.scala +++ /dev/null @@ -1,99 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - -package scala.xml -package include.sax -import scala.xml.include._ - -import java.io.InputStream -import scala.util.matching.Regex - -/** `EncodingHeuristics` reads from a stream - * (which should be buffered) and attempts to guess - * what the encoding of the text in the stream is. - * If it fails to determine the type of the encoding, - * it returns the default UTF-8. - * - * @author Burak Emir - * @author Paul Phillips - */ -object EncodingHeuristics -{ - object EncodingNames { - // UCS-4 isn't yet implemented in java releases anyway... - val bigUCS4 = "UCS-4" - val littleUCS4 = "UCS-4" - val unusualUCS4 = "UCS-4" - val bigUTF16 = "UTF-16BE" - val littleUTF16 = "UTF-16LE" - val utf8 = "UTF-8" - val default = utf8 - } - import EncodingNames._ - - /** This utility method attempts to determine the XML character encoding - * by examining the input stream, as specified at - * [[http://www.w3.org/TR/xml/#sec-guessing w3]]. - * - * @param in `InputStream` to read from. - * @throws IOException if the stream cannot be reset - * @return the name of the encoding. - */ - def readEncodingFromStream(in: InputStream): String = { - var ret: String = null - val bytesToRead = 1024 // enough to read most XML encoding declarations - def resetAndRet = { in.reset ; ret } - - // This may fail if there are a lot of space characters before the end - // of the encoding declaration - in mark bytesToRead - val bytes = (in.read, in.read, in.read, in.read) - - // first look for byte order mark - ret = bytes match { - case (0x00, 0x00, 0xFE, 0xFF) => bigUCS4 - case (0xFF, 0xFE, 0x00, 0x00) => littleUCS4 - case (0x00, 0x00, 0xFF, 0xFE) => unusualUCS4 - case (0xFE, 0xFF, 0x00, 0x00) => unusualUCS4 - case (0xFE, 0xFF, _ , _ ) => bigUTF16 - case (0xFF, 0xFE, _ , _ ) => littleUTF16 - case (0xEF, 0xBB, 0xBF, _ ) => utf8 - case _ => null - } - if (ret != null) - return resetAndRet - - def readASCIIEncoding: String = { - val data = new Array[Byte](bytesToRead - 4) - val length = in.read(data, 0, bytesToRead - 4) - - // Use Latin-1 (ISO-8859-1) because all byte sequences are legal. - val declaration = new String(data, 0, length, "ISO-8859-1") - val regexp = """(?m).*?encoding\s*=\s*["'](.+?)['"]""".r - (regexp findFirstMatchIn declaration) match { - case None => default - case Some(md) => md.subgroups(0) - } - } - - // no byte order mark present; first character must be '<' or whitespace - ret = bytes match { - case (0x00, 0x00, 0x00, '<' ) => bigUCS4 - case ('<' , 0x00, 0x00, 0x00) => littleUCS4 - case (0x00, 0x00, '<' , 0x00) => unusualUCS4 - case (0x00, '<' , 0x00, 0x00) => unusualUCS4 - case (0x00, '<' , 0x00, '?' ) => bigUTF16 // XXX must read encoding - case ('<' , 0x00, '?' , 0x00) => littleUTF16 // XXX must read encoding - case ('<' , '?' , 'x' , 'm' ) => readASCIIEncoding - case (0x4C, 0x6F, 0xA7, 0x94) => utf8 // XXX EBCDIC - case _ => utf8 // no XML or text declaration present - } - resetAndRet - } -} diff --git a/src/library/scala/xml/include/sax/Main.scala b/src/library/scala/xml/include/sax/Main.scala deleted file mode 100644 index 92d4d6ea73..0000000000 --- a/src/library/scala/xml/include/sax/Main.scala +++ /dev/null @@ -1,82 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - -package scala.xml -package include.sax - -import scala.util.control.Exception.{ catching, ignoring } -import org.xml.sax.XMLReader -import org.xml.sax.helpers.XMLReaderFactory - -@deprecated("Code example will be moved to documentation.", "2.10.0") -object Main { - private val namespacePrefixes = "http://xml.org/sax/features/namespace-prefixes" - private val lexicalHandler = "http://xml.org/sax/properties/lexical-handler" - - /** - * The driver method for xinc - * Output is written to System.out via Conolse - * </p> - * - * @param args contains the URLs and/or filenames - * of the documents to be processed. - */ - def main(args: Array[String]) { - def saxe[T](body: => T) = catching[T](classOf[SAXException]) opt body - def fail(msg: String) = System.err.println(msg) - - val parser: XMLReader = - saxe[XMLReader](XMLReaderFactory.createXMLReader()) getOrElse ( - saxe[XMLReader](XMLReaderFactory.createXMLReader(XercesClassName)) getOrElse ( - return fail("Could not find an XML parser") - ) - ) - - // Need better namespace handling - try parser.setFeature(namespacePrefixes, true) - catch { case e: SAXException => return System.err.println(e) } - - if (args.isEmpty) - return - - def dashR = args.size >= 2 && args(0) == "-r" - val args2 = if (dashR) args drop 2 else args - val resolver: Option[EntityResolver] = - if (dashR) None - else catching(classOf[Exception]) opt { - val r = Class.forName(args(1)).newInstance().asInstanceOf[EntityResolver] - parser setEntityResolver r - r - } orElse (return fail("Could not load requested EntityResolver")) - - for (arg <- args2) { - try { - val includer = new XIncludeFilter() - includer setParent parser - val s = new XIncluder(System.out, "UTF-8") - includer setContentHandler s - - resolver map (includer setEntityResolver _) - // SAXException here means will not support comments - ignoring(classOf[SAXException]) { - includer.setProperty(lexicalHandler, s) - s setFilter includer - } - includer parse arg - } - catch { - case e: SAXParseException => - fail(e.toString) - fail("Problem in %s at line %d".format(e.getSystemId, e.getLineNumber)) - case e: SAXException => - fail(e.toString) - } - } - } -} diff --git a/src/library/scala/xml/include/sax/XIncludeFilter.scala b/src/library/scala/xml/include/sax/XIncludeFilter.scala deleted file mode 100644 index 729769366e..0000000000 --- a/src/library/scala/xml/include/sax/XIncludeFilter.scala +++ /dev/null @@ -1,372 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala.xml -package include.sax - -import scala.xml.include._ - -import org.xml.sax.{ Attributes, XMLReader, Locator } -import org.xml.sax.helpers.{ XMLReaderFactory, XMLFilterImpl, NamespaceSupport, AttributesImpl } - -import java.io.{ InputStream, BufferedInputStream, InputStreamReader, IOException, UnsupportedEncodingException } -import java.util.Stack -import java.net.{ URL, MalformedURLException } - -/** This is a SAX filter which resolves all XInclude include elements before - * passing them on to the client application. Currently this class has the - * following known deviation from the XInclude specification: - * - * 1. XPointer is not supported. - * - * Furthermore, I would definitely use a new instance of this class for each - * document you want to process. I doubt it can be used successfully on - * multiple documents. Furthermore, I can virtually guarantee that this - * class is not thread safe. You have been warned. - * - * Since this class is not designed to be subclassed, and since I have not - * yet considered how that might affect the methods herein or what other - * protected methods might be needed to support subclasses, I have declared - * this class final. I may remove this restriction later, though the use-case - * for subclassing is weak. This class is designed to have its functionality - * extended via a horizontal chain of filters, not a vertical hierarchy of - * sub and superclasses. - * - * To use this class: - * - * - Construct an `XIncludeFilter` object with a known base URL - * - Pass the `XMLReader` object from which the raw document will be read to - * the `setParent()` method of this object. - * - Pass your own `ContentHandler` object to the `setContentHandler()` - * method of this object. This is the object which will receive events - * from the parsed and included document. - * - Optional: if you wish to receive comments, set your own `LexicalHandler` - * object as the value of this object's - * `http://xml.org/sax/properties/lexical-handler` property. - * Also make sure your `LexicalHandler` asks this object for the status of - * each comment using `insideIncludeElement` before doing anything with the - * comment. - * - Pass the URL of the document to read to this object's `parse()` method - * - * e.g. - * {{{ - * val includer = new XIncludeFilter(base) - * includer setParent parser - * includer setContentHandler new SAXXIncluder(System.out) - * includer parse args(i) - * }}} - * translated from Elliotte Rusty Harold's Java source. - * - * @author Burak Emir - */ -class XIncludeFilter extends XMLFilterImpl { - - final val XINCLUDE_NAMESPACE = "http://www.w3.org/2001/XInclude" - - private val bases = new Stack[URL]() - private val locators = new Stack[Locator]() - -/* private EntityResolver resolver; - - public XIncludeFilter() { - this(null); - } - - public XIncludeFilter(EntityResolver resolver) { - this.resolver = resolver; - } */ - - - // what if this isn't called???? - // do I need to check this in startDocument() and push something - // there???? - override def setDocumentLocator(locator: Locator) { - locators push locator - val base = locator.getSystemId() - try { - bases.push(new URL(base)) - } - catch { - case e:MalformedURLException => - throw new UnsupportedOperationException("Unrecognized SYSTEM ID: " + base) - } - super.setDocumentLocator(locator) - } - - - // necessary to throw away contents of non-empty XInclude elements - private var level = 0 - - /** This utility method returns true if and only if this reader is - * currently inside a non-empty include element. (This is '''not''' the - * same as being inside the node set which replaces the include element.) - * This is primarily needed for comments inside include elements. - * It must be checked by the actual `LexicalHandler` to see whether - * a comment is passed or not. - * - * @return boolean - */ - def insideIncludeElement(): Boolean = level != 0 - - override def startElement(uri: String, localName: String, qName: String, atts1: Attributes) { - var atts = atts1 - if (level == 0) { // We're not inside an xi:include element - - // Adjust bases stack by pushing either the new - // value of xml:base or the base of the parent - val base = atts.getValue(NamespaceSupport.XMLNS, "base") - val parentBase = bases.peek().asInstanceOf[URL] - var currentBase = parentBase - if (base != null) { - try { - currentBase = new URL(parentBase, base) - } - catch { - case e: MalformedURLException => - throw new SAXException("Malformed base URL: " - + currentBase, e) - } - } - bases push currentBase - - if (uri.equals(XINCLUDE_NAMESPACE) && localName.equals("include")) { - // include external document - val href = atts.getValue("href") - // Verify that there is an href attribute - if (href == null) { - throw new SAXException("Missing href attribute") - } - - var parse = atts getValue "parse" - if (parse == null) parse = "xml" - - if (parse equals "text") { - val encoding = atts getValue "encoding" - includeTextDocument(href, encoding); - } - else if (parse equals "xml") { - includeXMLDocument(href); - } - // Need to check this also in DOM and JDOM???? - else { - throw new SAXException( - "Illegal value for parse attribute: " + parse) - } - level += 1 - } - else { - if (atRoot) { - // add xml:base attribute if necessary - val attsImpl = new AttributesImpl(atts) - attsImpl.addAttribute(NamespaceSupport.XMLNS, "base", - "xml:base", "CDATA", currentBase.toExternalForm()) - atts = attsImpl - atRoot = false - } - super.startElement(uri, localName, qName, atts) - } - } - } - - override def endElement(uri: String, localName: String, qName: String) { - if (uri.equals(XINCLUDE_NAMESPACE) - && localName.equals("include")) { - level -= 1 - } - else if (level == 0) { - bases.pop() - super.endElement(uri, localName, qName) - } - } - - private var depth = 0; - - override def startDocument() { - level = 0 - if (depth == 0) super.startDocument() - depth += 1 - } - - override def endDocument() { - locators.pop() - bases.pop() // pop the URL for the document itself - depth -= 1 - if (depth == 0) super.endDocument() - } - - // how do prefix mappings move across documents???? - override def startPrefixMapping(prefix: String , uri: String) { - if (level == 0) super.startPrefixMapping(prefix, uri) - } - - override def endPrefixMapping(prefix: String) { - if (level == 0) super.endPrefixMapping(prefix) - } - - override def characters(ch: Array[Char], start: Int, length: Int) { - if (level == 0) super.characters(ch, start, length) - } - - override def ignorableWhitespace(ch: Array[Char], start: Int, length: Int) { - if (level == 0) super.ignorableWhitespace(ch, start, length) - } - - override def processingInstruction(target: String, data: String) { - if (level == 0) super.processingInstruction(target, data) - } - - override def skippedEntity(name: String) { - if (level == 0) super.skippedEntity(name) - } - - // convenience method for error messages - private def getLocation(): String = { - var locationString = "" - val locator = locators.peek().asInstanceOf[Locator] - var publicID = "" - var systemID = "" - var column = -1 - var line = -1 - if (locator != null) { - publicID = locator.getPublicId() - systemID = locator.getSystemId() - line = locator.getLineNumber() - column = locator.getColumnNumber() - } - locationString = (" in document included from " + publicID - + " at " + systemID - + " at line " + line + ", column " + column); - - locationString - } - - /** This utility method reads a document at a specified URL and fires off - * calls to `characters()`. It's used to include files with `parse="text"`. - * - * @param url URL of the document that will be read - * @param encoding1 Encoding of the document; e.g. UTF-8, - * ISO-8859-1, etc. - * @return void - * @throws SAXException if the requested document cannot - be downloaded from the specified URL - or if the encoding is not recognized - */ - private def includeTextDocument(url: String, encoding1: String) { - var encoding = encoding1 - if (encoding == null || encoding.trim().equals("")) encoding = "UTF-8"; - var source: URL = null - try { - val base = bases.peek().asInstanceOf[URL] - source = new URL(base, url) - } - catch { - case e: MalformedURLException => - val ex = new UnavailableResourceException("Unresolvable URL " + url - + getLocation()) - ex.setRootCause(e) - throw new SAXException("Unresolvable URL " + url + getLocation(), ex) - } - - try { - val uc = source.openConnection() - val in = new BufferedInputStream(uc.getInputStream()) - var encodingFromHeader = uc.getContentEncoding() - var contentType = uc.getContentType() - if (encodingFromHeader != null) - encoding = encodingFromHeader - else { - // What if file does not have a MIME type but name ends in .xml???? - // MIME types are case-insensitive - // Java may be picking this up from file URL - if (contentType != null) { - contentType = contentType.toLowerCase(); - if (contentType.equals("text/xml") - || contentType.equals("application/xml") - || (contentType.startsWith("text/") && contentType.endsWith("+xml") ) - || (contentType.startsWith("application/") && contentType.endsWith("+xml"))) { - encoding = EncodingHeuristics.readEncodingFromStream(in); - } - } - } - val reader = new InputStreamReader(in, encoding) - val c = new Array[Char](1024) - var charsRead: Int = 0 // bogus init value - do { - charsRead = reader.read(c, 0, 1024) - if (charsRead > 0) this.characters(c, 0, charsRead) - } while (charsRead != -1) - } - catch { - case e: UnsupportedEncodingException => - throw new SAXException("Unsupported encoding: " - + encoding + getLocation(), e) - case e: IOException => - throw new SAXException("Document not found: " - + source.toExternalForm() + getLocation(), e) - } - - } - - private var atRoot = false - - /** This utility method reads a document at a specified URL - * and fires off calls to various `ContentHandler` methods. - * It's used to include files with `parse="xml"`. - * - * @param url URL of the document that will be read - * @return void - * @throws SAXException if the requested document cannot - be downloaded from the specified URL. - */ - private def includeXMLDocument(url: String) { - val source = - try new URL(bases.peek(), url) - catch { - case e: MalformedURLException => - val ex = new UnavailableResourceException("Unresolvable URL " + url + getLocation()) - ex setRootCause e - throw new SAXException("Unresolvable URL " + url + getLocation(), ex) - } - - try { - val parser: XMLReader = - try XMLReaderFactory.createXMLReader() - catch { - case e: SAXException => - try XMLReaderFactory.createXMLReader(XercesClassName) - catch { case _: SAXException => return System.err.println("Could not find an XML parser") } - } - - parser setContentHandler this - val resolver = this.getEntityResolver() - if (resolver != null) - parser setEntityResolver resolver - - // save old level and base - val previousLevel = level - this.level = 0 - if (bases contains source) - throw new SAXException( - "Circular XInclude Reference", - new CircularIncludeException("Circular XInclude Reference to " + source + getLocation()) - ) - - bases push source - atRoot = true - parser parse source.toExternalForm() - - // restore old level and base - this.level = previousLevel - bases.pop() - } - catch { - case e: IOException => - throw new SAXException("Document not found: " + source.toExternalForm() + getLocation(), e) - } - } -} diff --git a/src/library/scala/xml/include/sax/XIncluder.scala b/src/library/scala/xml/include/sax/XIncluder.scala deleted file mode 100644 index 5064d6b3d8..0000000000 --- a/src/library/scala/xml/include/sax/XIncluder.scala +++ /dev/null @@ -1,188 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - -package scala.xml -package include.sax - -import scala.xml.include._ -import scala.collection.mutable -import org.xml.sax.{ ContentHandler, XMLReader, Locator, Attributes } -import org.xml.sax.ext.LexicalHandler -import java.io.{ File, OutputStream, OutputStreamWriter, Writer, IOException } - -/** XIncluder is a SAX `ContentHandler` that writes its XML document onto - * an output stream after resolving all `xinclude:include` elements. - * - * Based on Eliotte Rusty Harold's SAXXIncluder. - */ -class XIncluder(outs: OutputStream, encoding: String) extends ContentHandler with LexicalHandler { - - var out = new OutputStreamWriter(outs, encoding) - - def setDocumentLocator(locator: Locator) {} - - def startDocument() { - try { - out.write("<?xml version='1.0' encoding='" - + encoding + "'?>\r\n"); - } - catch { - case e:IOException => - throw new SAXException("Write failed", e) - } - } - - def endDocument() { - try { - out.flush() - } - catch { - case e:IOException => - throw new SAXException("Flush failed", e) - } - } - - def startPrefixMapping(prefix: String , uri: String) {} - - def endPrefixMapping(prefix: String) {} - - def startElement(namespaceURI: String, localName: String, qualifiedName: String, atts: Attributes) = { - try { - out.write("<" + qualifiedName); - var i = 0; while (i < atts.getLength()) { - out.write(" "); - out.write(atts.getQName(i)); - out.write("='"); - val value = atts.getValue(i); - // @todo Need to use character references if the encoding - // can't support the character - out.write(scala.xml.Utility.escape(value)) - out.write("'"); - i += 1 - } - out.write(">") - } - catch { - case e:IOException => - throw new SAXException("Write failed", e) - } - } - - def endElement(namespaceURI: String, localName:String, qualifiedName: String) { - try { - out.write("</" + qualifiedName + ">") - } - catch { - case e: IOException => - throw new SAXException("Write failed", e) - } - } - - // need to escape characters that are not in the given - // encoding using character references???? - def characters(ch: Array[Char], start: Int, length: Int) { - try { - var i = 0; while (i < length) { - val c = ch(start+i); - if (c == '&') out.write("&"); - else if (c == '<') out.write("<"); - // This next fix is normally not necessary. - // However, it is required if text contains ]]> - // (The end CDATA section delimiter) - else if (c == '>') out.write(">"); - else out.write(c); - i += 1 - } - } - catch { - case e: IOException => - throw new SAXException("Write failed", e); - } - } - - def ignorableWhitespace(ch: Array[Char], start: Int , length: Int) { - this.characters(ch, start, length) - } - - // do I need to escape text in PI???? - def processingInstruction(target: String, data: String) { - try { - out.write("<?" + target + " " + data + "?>") - } - catch { - case e:IOException => - throw new SAXException("Write failed", e) - } - } - - def skippedEntity(name: String) { - try { - out.write("&" + name + ";") - } - catch { - case e:IOException => - throw new SAXException("Write failed", e) - } - } - - // LexicalHandler methods - private var inDTD: Boolean = false - private val entities = new mutable.Stack[String]() - - def startDTD(name: String, publicID: String, systemID: String) { - inDTD = true - // if this is the source document, output a DOCTYPE declaration - if (entities.isEmpty) { - var id = "" - if (publicID != null) id = " PUBLIC \"" + publicID + "\" \"" + systemID + '"'; - else if (systemID != null) id = " SYSTEM \"" + systemID + '"'; - try { - out.write("<!DOCTYPE " + name + id + ">\r\n") - } - catch { - case e:IOException => - throw new SAXException("Error while writing DOCTYPE", e) - } - } - } - def endDTD() {} - - def startEntity(name: String) { - entities push name - } - - def endEntity(name: String) { - entities.pop() - } - - def startCDATA() {} - def endCDATA() {} - - // Just need this reference so we can ask if a comment is - // inside an include element or not - private var filter: XIncludeFilter = null - - def setFilter(filter: XIncludeFilter) { - this.filter = filter - } - - def comment(ch: Array[Char], start: Int, length: Int) { - if (!inDTD && !filter.insideIncludeElement()) { - try { - out.write("<!--") - out.write(ch, start, length) - out.write("-->") - } - catch { - case e: IOException => - throw new SAXException("Write failed", e) - } - } - } -} diff --git a/src/library/scala/xml/package.scala b/src/library/scala/xml/package.scala deleted file mode 100644 index 4001cc5ffb..0000000000 --- a/src/library/scala/xml/package.scala +++ /dev/null @@ -1,19 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala - -package object xml { - val XercesClassName = "org.apache.xerces.parsers.SAXParser" - - type SAXException = org.xml.sax.SAXException - type SAXParseException = org.xml.sax.SAXParseException - type EntityResolver = org.xml.sax.EntityResolver - type InputSource = org.xml.sax.InputSource - type SAXParser = javax.xml.parsers.SAXParser -} diff --git a/src/library/scala/xml/parsing/ConstructingHandler.scala b/src/library/scala/xml/parsing/ConstructingHandler.scala deleted file mode 100755 index 6fda4dabfb..0000000000 --- a/src/library/scala/xml/parsing/ConstructingHandler.scala +++ /dev/null @@ -1,33 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - - -package scala.xml -package parsing - -/** Implementation of MarkupHandler that constructs nodes. - * - * @author Burak Emir - * @version 1.0 - */ -abstract class ConstructingHandler extends MarkupHandler -{ - val preserveWS: Boolean - - def elem(pos: Int, pre: String, label: String, attrs: MetaData, - pscope: NamespaceBinding, empty: Boolean, nodes: NodeSeq): NodeSeq = - Elem(pre, label, attrs, pscope, empty, nodes:_*) - - def procInstr(pos: Int, target: String, txt: String) = - ProcInstr(target, txt) - - def comment(pos: Int, txt: String) = Comment(txt) - def entityRef(pos: Int, n: String) = EntityRef(n) - def text(pos: Int, txt: String) = Text(txt) -} diff --git a/src/library/scala/xml/parsing/ConstructingParser.scala b/src/library/scala/xml/parsing/ConstructingParser.scala deleted file mode 100644 index 404411812e..0000000000 --- a/src/library/scala/xml/parsing/ConstructingParser.scala +++ /dev/null @@ -1,54 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - - -package scala.xml -package parsing - -import java.io.File -import scala.io.Source - -object ConstructingParser { - def fromFile(inp: File, preserveWS: Boolean) = - new ConstructingParser(Source.fromFile(inp), preserveWS).initialize - - def fromSource(inp: Source, preserveWS: Boolean) = - new ConstructingParser(inp, preserveWS).initialize -} - -/** An xml parser. parses XML and invokes callback methods of a MarkupHandler. - * Don't forget to call next.ch on a freshly instantiated parser in order to - * initialize it. If you get the parser from the object method, initialization - * is already done for you. - * - * {{{ - * object parseFromURL { - * def main(args: Array[String]) { - * val url = args(0) - * val src = scala.io.Source.fromURL(url) - * val cpa = scala.xml.parsing.ConstructingParser.fromSource(src, false) // fromSource initializes automatically - * val doc = cpa.document() - * - * // let's see what it is - * val ppr = new scala.xml.PrettyPrinter(80, 5) - * val ele = doc.docElem - * println("finished parsing") - * val out = ppr.format(ele) - * println(out) - * } - * } - * }}} */ -class ConstructingParser(val input: Source, val preserveWS: Boolean) -extends ConstructingHandler -with ExternalSources -with MarkupParser { - - // default impl. of Logged - override def log(msg: String): Unit = {} -} diff --git a/src/library/scala/xml/parsing/DefaultMarkupHandler.scala b/src/library/scala/xml/parsing/DefaultMarkupHandler.scala deleted file mode 100755 index 0152e44cda..0000000000 --- a/src/library/scala/xml/parsing/DefaultMarkupHandler.scala +++ /dev/null @@ -1,29 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - - -package scala.xml -package parsing - - -/** Default implementation of markup handler always returns `NodeSeq.Empty` */ -abstract class DefaultMarkupHandler extends MarkupHandler { - - def elem(pos: Int, pre: String, label: String, attrs: MetaData, - scope:NamespaceBinding, empty: Boolean, args: NodeSeq) = NodeSeq.Empty - - def procInstr(pos: Int, target: String, txt: String) = NodeSeq.Empty - - def comment(pos: Int, comment: String ): NodeSeq = NodeSeq.Empty - - def entityRef(pos: Int, n: String) = NodeSeq.Empty - - def text(pos: Int, txt:String) = NodeSeq.Empty - -} diff --git a/src/library/scala/xml/parsing/ExternalSources.scala b/src/library/scala/xml/parsing/ExternalSources.scala deleted file mode 100644 index aaac588092..0000000000 --- a/src/library/scala/xml/parsing/ExternalSources.scala +++ /dev/null @@ -1,37 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - - -package scala.xml -package parsing - -import java.net.URL -import java.io.File.separator - -import scala.io.Source - -/** - * @author Burak Emir - * @version 1.0 - */ -trait ExternalSources { - self: ExternalSources with MarkupParser with MarkupHandler => - - def externalSource(systemId: String): Source = { - if (systemId startsWith "http:") - return Source fromURL new URL(systemId) - - val fileStr: String = input.descr match { - case x if x startsWith "file:" => x drop 5 - case x => x take ((x lastIndexOf separator) + 1) - } - - Source.fromFile(fileStr + systemId) - } -} diff --git a/src/library/scala/xml/parsing/FactoryAdapter.scala b/src/library/scala/xml/parsing/FactoryAdapter.scala deleted file mode 100644 index 5f776f5299..0000000000 --- a/src/library/scala/xml/parsing/FactoryAdapter.scala +++ /dev/null @@ -1,186 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala.xml -package parsing - -import java.io.{ InputStream, Reader, File, FileDescriptor, FileInputStream } -import scala.collection.{ mutable, Iterator } -import org.xml.sax.Attributes -import org.xml.sax.helpers.DefaultHandler - -// can be mixed into FactoryAdapter if desired -trait ConsoleErrorHandler extends DefaultHandler { - // ignore warning, crimson warns even for entity resolution! - override def warning(ex: SAXParseException): Unit = { } - override def error(ex: SAXParseException): Unit = printError("Error", ex) - override def fatalError(ex: SAXParseException): Unit = printError("Fatal Error", ex) - - protected def printError(errtype: String, ex: SAXParseException): Unit = - Console.withOut(Console.err) { - val s = "[%s]:%d:%d: %s".format( - errtype, ex.getLineNumber, ex.getColumnNumber, ex.getMessage) - Console.println(s) - Console.flush - } -} - -/** SAX adapter class, for use with Java SAX parser. Keeps track of - * namespace bindings, without relying on namespace handling of the - * underlying SAX parser. - */ -abstract class FactoryAdapter extends DefaultHandler with factory.XMLLoader[Node] { - var rootElem: Node = null - - val buffer = new StringBuilder() - val attribStack = new mutable.Stack[MetaData] - val hStack = new mutable.Stack[Node] // [ element ] contains siblings - val tagStack = new mutable.Stack[String] - var scopeStack = new mutable.Stack[NamespaceBinding] - - var curTag : String = null - var capture: Boolean = false - - // abstract methods - - /** Tests if an XML element contains text. - * @return true if element named `localName` contains text. - */ - def nodeContainsText(localName: String): Boolean // abstract - - /** creates an new non-text(tree) node. - * @param elemName - * @param attribs - * @param chIter - * @return a new XML element. - */ - def createNode(pre: String, elemName: String, attribs: MetaData, - scope: NamespaceBinding, chIter: List[Node]): Node // abstract - - /** creates a Text node. - * @param text - * @return a new Text node. - */ - def createText(text: String): Text // abstract - - /** creates a new processing instruction node. - */ - def createProcInstr(target: String, data: String): Seq[ProcInstr] - - // - // ContentHandler methods - // - - val normalizeWhitespace = false - - /** Characters. - * @param ch - * @param offset - * @param length - */ - override def characters(ch: Array[Char], offset: Int, length: Int): Unit = { - if (!capture) return - // compliant: report every character - else if (!normalizeWhitespace) buffer.appendAll(ch, offset, length) - // normalizing whitespace is not compliant, but useful - else { - var it = ch.slice(offset, offset + length).iterator - while (it.hasNext) { - val c = it.next - val isSpace = c.isWhitespace - buffer append (if (isSpace) ' ' else c) - if (isSpace) - it = it dropWhile (_.isWhitespace) - } - } - } - - private def splitName(s: String) = { - val idx = s indexOf ':' - if (idx < 0) (null, s) - else (s take idx, s drop (idx + 1)) - } - - /* ContentHandler methods */ - - /* Start element. */ - override def startElement( - uri: String, - _localName: String, - qname: String, - attributes: Attributes): Unit = - { - captureText() - tagStack push curTag - curTag = qname - - val localName = splitName(qname)._2 - capture = nodeContainsText(localName) - - hStack push null - var m: MetaData = Null - var scpe: NamespaceBinding = - if (scopeStack.isEmpty) TopScope - else scopeStack.top - - for (i <- 0 until attributes.getLength()) { - val qname = attributes getQName i - val value = attributes getValue i - val (pre, key) = splitName(qname) - def nullIfEmpty(s: String) = if (s == "") null else s - - if (pre == "xmlns" || (pre == null && qname == "xmlns")) { - val arg = if (pre == null) null else key - scpe = new NamespaceBinding(arg, nullIfEmpty(value), scpe) - } - else - m = Attribute(Option(pre), key, Text(value), m) - } - - scopeStack push scpe - attribStack push m - } - - - /** captures text, possibly normalizing whitespace - */ - def captureText(): Unit = { - if (capture && buffer.length > 0) - hStack push createText(buffer.toString) - - buffer.clear() - } - - /** End element. - * @param uri - * @param _localName - * @param qname - * @throws org.xml.sax.SAXException if .. - */ - override def endElement(uri: String , _localName: String, qname: String): Unit = { - captureText() - val metaData = attribStack.pop - - // reverse order to get it right - val v = (Iterator continually hStack.pop takeWhile (_ != null)).toList.reverse - val (pre, localName) = splitName(qname) - val scp = scopeStack.pop - - // create element - rootElem = createNode(pre, localName, metaData, scp, v) - hStack push rootElem - curTag = tagStack.pop - capture = curTag != null && nodeContainsText(curTag) // root level - } - - /** Processing instruction. - */ - override def processingInstruction(target: String, data: String) { - hStack pushAll createProcInstr(target, data) - } -} diff --git a/src/library/scala/xml/parsing/FatalError.scala b/src/library/scala/xml/parsing/FatalError.scala deleted file mode 100644 index a8b4f8f8cf..0000000000 --- a/src/library/scala/xml/parsing/FatalError.scala +++ /dev/null @@ -1,16 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - - -package scala.xml -package parsing - -/** !!! This is poorly named, but I guess it's in the API. - */ -case class FatalError(msg: String) extends java.lang.RuntimeException(msg) diff --git a/src/library/scala/xml/parsing/MarkupHandler.scala b/src/library/scala/xml/parsing/MarkupHandler.scala deleted file mode 100755 index 7028161821..0000000000 --- a/src/library/scala/xml/parsing/MarkupHandler.scala +++ /dev/null @@ -1,124 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - - -package scala.xml -package parsing - -import scala.collection.mutable -import scala.io.Source -import scala.util.logging.Logged -import scala.xml.dtd._ - -/** class that handles markup - provides callback methods to MarkupParser. - * the default is nonvalidating behaviour - * - * @author Burak Emir - * @version 1.0 - * - * @todo can we ignore more entity declarations (i.e. those with extIDs)? - * @todo expanding entity references - */ -abstract class MarkupHandler extends Logged -{ - /** returns true is this markup handler is validating */ - val isValidating: Boolean = false - - var decls: List[Decl] = Nil - var ent: mutable.Map[String, EntityDecl] = new mutable.HashMap[String, EntityDecl]() - - def lookupElemDecl(Label: String): ElemDecl = { - for (z @ ElemDecl(Label, _) <- decls) - return z - - null - } - - def replacementText(entityName: String): Source = - Source fromString ((ent get entityName) match { - case Some(ParsedEntityDecl(_, IntDef(value))) => value - case Some(ParameterEntityDecl(_, IntDef(value))) => " %s " format value - case Some(_) => "<!-- %s; -->" format entityName - case None => "<!-- unknown entity %s; -->" format entityName - }) - - def endDTD(n: String): Unit = () - - /** callback method invoked by MarkupParser after start-tag of element. - * - * @param pos the position in the sourcefile - * @param pre the prefix - * @param label the local name - * @param attrs the attributes (metadata) - */ - def elemStart(pos: Int, pre: String, label: String, attrs: MetaData, scope: NamespaceBinding): Unit = () - - /** callback method invoked by MarkupParser after end-tag of element. - * - * @param pos the position in the source file - * @param pre the prefix - * @param label the local name - */ - def elemEnd(pos: Int, pre: String, label: String): Unit = () - - /** callback method invoked by MarkupParser after parsing an element, - * between the elemStart and elemEnd callbacks - * - * @param pos the position in the source file - * @param pre the prefix - * @param label the local name - * @param attrs the attributes (metadata) - * @param empty `true` if the element was previously empty; `false` otherwise. - * @param args the children of this element - */ - def elem(pos: Int, pre: String, label: String, attrs: MetaData, scope: NamespaceBinding, empty: Boolean, args: NodeSeq): NodeSeq - - /** callback method invoked by MarkupParser after parsing PI. - */ - def procInstr(pos: Int, target: String, txt: String): NodeSeq - - /** callback method invoked by MarkupParser after parsing comment. - */ - def comment(pos: Int, comment: String): NodeSeq - - /** callback method invoked by MarkupParser after parsing entity ref. - * @todo expanding entity references - */ - def entityRef(pos: Int, n: String): NodeSeq - - /** callback method invoked by MarkupParser after parsing text. - */ - def text(pos: Int, txt: String): NodeSeq - - // DTD handler methods - - def elemDecl(n: String, cmstr: String): Unit = () - - def attListDecl(name: String, attList: List[AttrDecl]): Unit = () - - private def someEntityDecl(name: String, edef: EntityDef, f: (String, EntityDef) => EntityDecl): Unit = - edef match { - case _: ExtDef if !isValidating => // ignore (cf REC-xml 4.4.1) - case _ => - val y = f(name, edef) - decls ::= y - ent.update(name, y) - } - - def parameterEntityDecl(name: String, edef: EntityDef): Unit = - someEntityDecl(name, edef, ParameterEntityDecl.apply _) - - def parsedEntityDecl(name: String, edef: EntityDef): Unit = - someEntityDecl(name, edef, ParsedEntityDecl.apply _) - - def peReference(name: String) { decls ::= PEReference(name) } - def unparsedEntityDecl(name: String, extID: ExternalID, notat: String): Unit = () - def notationDecl(notat: String, extID: ExternalID): Unit = () - def reportSyntaxError(pos: Int, str: String): Unit -} diff --git a/src/library/scala/xml/parsing/MarkupParser.scala b/src/library/scala/xml/parsing/MarkupParser.scala deleted file mode 100755 index f9ff54d054..0000000000 --- a/src/library/scala/xml/parsing/MarkupParser.scala +++ /dev/null @@ -1,941 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala.xml -package parsing - -import scala.io.Source -import scala.xml.dtd._ -import Utility.Escapes.{ pairs => unescape } - -/** - * An XML parser. - * - * Parses XML 1.0, invokes callback methods of a `MarkupHandler` and returns - * whatever the markup handler returns. Use `ConstructingParser` if you just - * want to parse XML to construct instances of `scala.xml.Node`. - * - * While XML elements are returned, DTD declarations - if handled - are - * collected using side-effects. - * - * @author Burak Emir - * @version 1.0 - */ -trait MarkupParser extends MarkupParserCommon with TokenTests -{ - self: MarkupParser with MarkupHandler => - - type PositionType = Int - type InputType = Source - type ElementType = NodeSeq - type AttributesType = (MetaData, NamespaceBinding) - type NamespaceType = NamespaceBinding - - def truncatedError(msg: String): Nothing = throw FatalError(msg) - def errorNoEnd(tag: String) = throw FatalError("expected closing tag of " + tag) - - def xHandleError(that: Char, msg: String) = reportSyntaxError(msg) - - val input: Source - - /** if true, does not remove surplus whitespace */ - val preserveWS: Boolean - - def externalSource(systemLiteral: String): Source - - // - // variables, values - // - - protected var curInput: Source = input - - // See ticket #3720 for motivations. - private class WithLookAhead(underlying: Source) extends Source { - private val queue = scala.collection.mutable.Queue[Char]() - def lookahead(): BufferedIterator[Char] = { - val iter = queue.iterator ++ new Iterator[Char] { - def hasNext = underlying.hasNext - def next() = { val x = underlying.next(); queue += x; x } - } - iter.buffered - } - val iter = new Iterator[Char] { - def hasNext = underlying.hasNext || !queue.isEmpty - def next() = if (!queue.isEmpty) queue.dequeue() else underlying.next() - } - } - - def lookahead(): BufferedIterator[Char] = curInput match { - case curInputWLA:WithLookAhead => - curInputWLA.lookahead() - case _ => - val newInput = new WithLookAhead(curInput) - curInput = newInput - newInput.lookahead() - } - - - /** the handler of the markup, returns this */ - private val handle: MarkupHandler = this - - /** stack of inputs */ - var inpStack: List[Source] = Nil - - /** holds the position in the source file */ - var pos: Int = _ - - /* used when reading external subset */ - var extIndex = -1 - - /** holds temporary values of pos */ - var tmppos: Int = _ - - /** holds the next character */ - var nextChNeeded: Boolean = false - var reachedEof: Boolean = false - var lastChRead: Char = _ - def ch: Char = { - if (nextChNeeded) { - if (curInput.hasNext) { - lastChRead = curInput.next - pos = curInput.pos - } else { - val ilen = inpStack.length; - //Console.println(" ilen = "+ilen+ " extIndex = "+extIndex); - if ((ilen != extIndex) && (ilen > 0)) { - /** for external source, inpStack == Nil ! need notify of eof! */ - pop() - } else { - reachedEof = true - lastChRead = 0.asInstanceOf[Char] - } - } - nextChNeeded = false - } - lastChRead - } - - /** character buffer, for names */ - protected val cbuf = new StringBuilder() - - var dtd: DTD = null - - protected var doc: Document = null - - def eof: Boolean = { ch; reachedEof } - - // - // methods - // - - /** {{{ - * <? prolog ::= xml S ... ?> - * }}} */ - def xmlProcInstr(): MetaData = { - xToken("xml") - xSpace - val (md,scp) = xAttributes(TopScope) - if (scp != TopScope) - reportSyntaxError("no xmlns definitions here, please."); - xToken('?') - xToken('>') - md - } - - /** Factored out common code. - */ - private def prologOrTextDecl(isProlog: Boolean): (Option[String], Option[String], Option[Boolean]) = { - var info_ver: Option[String] = None - var info_enc: Option[String] = None - var info_stdl: Option[Boolean] = None - - var m = xmlProcInstr() - var n = 0 - - if (isProlog) - xSpaceOpt - - m("version") match { - case null => - case Text("1.0") => info_ver = Some("1.0"); n += 1 - case _ => reportSyntaxError("cannot deal with versions != 1.0") - } - - m("encoding") match { - case null => - case Text(enc) => - if (!isValidIANAEncoding(enc)) - reportSyntaxError("\"" + enc + "\" is not a valid encoding") - else { - info_enc = Some(enc) - n += 1 - } - } - - if (isProlog) { - m("standalone") match { - case null => - case Text("yes") => info_stdl = Some(true); n += 1 - case Text("no") => info_stdl = Some(false); n += 1 - case _ => reportSyntaxError("either 'yes' or 'no' expected") - } - } - - if (m.length - n != 0) { - val s = if (isProlog) "SDDecl? " else "" - reportSyntaxError("VersionInfo EncodingDecl? %sor '?>' expected!" format s) - } - - (info_ver, info_enc, info_stdl) - } - - /** {{{ - * <? prolog ::= xml S? - * // this is a bit more lenient than necessary... - * }}} */ - def prolog(): (Option[String], Option[String], Option[Boolean]) = - prologOrTextDecl(true) - - /** prolog, but without standalone */ - def textDecl(): (Option[String], Option[String]) = - prologOrTextDecl(false) match { case (x1, x2, _) => (x1, x2) } - - /** {{{ - * [22] prolog ::= XMLDecl? Misc* (doctypedecl Misc*)? - * [23] XMLDecl ::= '<?xml' VersionInfo EncodingDecl? SDDecl? S? '?>' - * [24] VersionInfo ::= S 'version' Eq ("'" VersionNum "'" | '"' VersionNum '"') - * [25] Eq ::= S? '=' S? - * [26] VersionNum ::= '1.0' - * [27] Misc ::= Comment | PI | S - * }}} */ - def document(): Document = { - doc = new Document() - - this.dtd = null - var info_prolog: (Option[String], Option[String], Option[Boolean]) = (None, None, None) - if ('<' != ch) { - reportSyntaxError("< expected") - return null - } - - nextch // is prolog ? - var children: NodeSeq = null - if ('?' == ch) { - nextch - info_prolog = prolog() - doc.version = info_prolog._1 - doc.encoding = info_prolog._2 - doc.standAlone = info_prolog._3 - - children = content(TopScope) // DTD handled as side effect - } - else { - val ts = new NodeBuffer() - content1(TopScope, ts) // DTD handled as side effect - ts &+ content(TopScope) - children = NodeSeq.fromSeq(ts) - } - //println("[MarkupParser::document] children now: "+children.toList) - var elemCount = 0 - var theNode: Node = null - for (c <- children) c match { - case _:ProcInstr => - case _:Comment => - case _:EntityRef => // todo: fix entities, shouldn't be "special" - reportSyntaxError("no entity references allowed here"); - case s:SpecialNode => - if (s.toString.trim().length > 0) //non-empty text nodes not allowed - elemCount += 2 - case m:Node => - elemCount += 1 - theNode = m - } - if (1 != elemCount) { - reportSyntaxError("document must contain exactly one element") - Console.println(children.toList) - } - - doc.children = children - doc.docElem = theNode - doc - } - - /** append Unicode character to name buffer*/ - protected def putChar(c: Char) = cbuf append c - - /** As the current code requires you to call nextch once manually - * after construction, this method formalizes that suboptimal reality. - */ - def initialize: this.type = { - nextch - this - } - - protected def ch_returning_nextch: Char = { val res = ch; nextch(); res } - - def mkAttributes(name: String, pscope: NamespaceBinding): AttributesType = - if (isNameStart (ch)) xAttributes(pscope) - else (Null, pscope) - - def mkProcInstr(position: Int, name: String, text: String): ElementType = - handle.procInstr(position, name, text) - - /** this method tells ch to get the next character when next called */ - def nextch() { - // Read current ch if needed - ch - - // Mark next ch to be required - nextChNeeded = true - } - - /** parse attribute and create namespace scope, metadata - * {{{ - * [41] Attributes ::= { S Name Eq AttValue } - * }}} - */ - def xAttributes(pscope: NamespaceBinding): (MetaData, NamespaceBinding) = { - var scope: NamespaceBinding = pscope - var aMap: MetaData = Null - while (isNameStart(ch)) { - val pos = this.pos - - val qname = xName - val _ = xEQ - val value = xAttributeValue() - - Utility.prefix(qname) match { - case Some("xmlns") => - val prefix = qname.substring(6 /*xmlns:*/ , qname.length) - scope = new NamespaceBinding(prefix, value, scope) - - case Some(prefix) => - val key = qname.substring(prefix.length+1, qname.length) - aMap = new PrefixedAttribute(prefix, key, Text(value), aMap) - - case _ => - if( qname == "xmlns" ) - scope = new NamespaceBinding(null, value, scope) - else - aMap = new UnprefixedAttribute(qname, Text(value), aMap) - } - - if ((ch != '/') && (ch != '>') && ('?' != ch)) - xSpace - } - - if(!aMap.wellformed(scope)) - reportSyntaxError( "double attribute"); - - (aMap,scope) - } - - /** entity value, terminated by either ' or ". value may not contain <. - * {{{ - * AttValue ::= `'` { _ } `'` - * | `"` { _ } `"` - * }}} - */ - def xEntityValue(): String = { - val endch = ch - nextch - while (ch != endch && !eof) { - putChar(ch) - nextch - } - nextch - val str = cbuf.toString() - cbuf.length = 0 - str - } - - /** {{{ - * '<! CharData ::= [CDATA[ ( {char} - {char}"]]>"{char} ) ']]>' - * - * see [15] - * }}} */ - def xCharData: NodeSeq = { - xToken("[CDATA[") - def mkResult(pos: Int, s: String): NodeSeq = { - handle.text(pos, s) - PCData(s) - } - xTakeUntil(mkResult, () => pos, "]]>") - } - - /** {{{ - * Comment ::= '<!--' ((Char - '-') | ('-' (Char - '-')))* '-->' - * - * see [15] - * }}} */ - def xComment: NodeSeq = { - val sb: StringBuilder = new StringBuilder() - xToken("--") - while (true) { - if (ch == '-' && { sb.append(ch); nextch; ch == '-' }) { - sb.length = sb.length - 1 - nextch - xToken('>') - return handle.comment(pos, sb.toString()) - } else sb.append(ch) - nextch - } - throw FatalError("this cannot happen") - } - - /* todo: move this into the NodeBuilder class */ - def appendText(pos: Int, ts: NodeBuffer, txt: String): Unit = { - if (preserveWS) - ts &+ handle.text(pos, txt); - else - for (t <- TextBuffer.fromString(txt).toText) { - ts &+ handle.text(pos, t.text); - } - } - - /** {{{ - * '<' content1 ::= ... - * }}} */ - def content1(pscope: NamespaceBinding, ts: NodeBuffer) { - ch match { - case '!' => - nextch - if ('[' == ch) // CDATA - ts &+ xCharData - else if ('D' == ch) // doctypedecl, parse DTD // @todo REMOVE HACK - parseDTD() - else // comment - ts &+ xComment - case '?' => // PI - nextch - ts &+ xProcInstr - case _ => - ts &+ element1(pscope) // child - } - } - - /** {{{ - * content1 ::= '<' content1 | '&' charref ... - * }}} */ - def content(pscope: NamespaceBinding): NodeSeq = { - var ts = new NodeBuffer - var exit = eof - // todo: optimize seq repr. - def done = new NodeSeq { val theSeq = ts.toList } - - while (!exit) { - tmppos = pos - exit = eof - - if (eof) - return done - - ch match { - case '<' => // another tag - nextch; ch match { - case '/' => exit = true // end tag - case _ => content1(pscope, ts) - } - - // postcond: xEmbeddedBlock == false! - case '&' => // EntityRef or CharRef - nextch; ch match { - case '#' => // CharacterRef - nextch - val theChar = handle.text(tmppos, xCharRef(() => ch, () => nextch)) - xToken(';'); - ts &+ theChar - case _ => // EntityRef - val n = xName - xToken(';') - - if (unescape contains n) { - handle.entityRef(tmppos, n) - ts &+ unescape(n) - } else push(n) - } - case _ => // text content - appendText(tmppos, ts, xText) - } - } - done - } // content(NamespaceBinding) - - /** {{{ - * externalID ::= SYSTEM S syslit - * PUBLIC S pubid S syslit - * }}} */ - def externalID(): ExternalID = ch match { - case 'S' => - nextch - xToken("YSTEM") - xSpace - val sysID = systemLiteral() - new SystemID(sysID) - case 'P' => - nextch; xToken("UBLIC") - xSpace - val pubID = pubidLiteral() - xSpace - val sysID = systemLiteral() - new PublicID(pubID, sysID) - } - - - /** parses document type declaration and assigns it to instance variable - * dtd. - * {{{ - * <! parseDTD ::= DOCTYPE name ... > - * }}} */ - def parseDTD() { // dirty but fast - var extID: ExternalID = null - if (this.dtd ne null) - reportSyntaxError("unexpected character (DOCTYPE already defined") - xToken("DOCTYPE") - xSpace - val n = xName - xSpace - //external ID - if ('S' == ch || 'P' == ch) { - extID = externalID() - xSpaceOpt - } - - /* parse external subset of DTD - */ - - if ((null != extID) && isValidating) { - - pushExternal(extID.systemId) - extIndex = inpStack.length - - extSubset() - pop() - extIndex = -1 - } - - if ('[' == ch) { // internal subset - nextch - /* TODO */ - intSubset() - // TODO: do the DTD parsing?? ?!?!?!?!! - xToken(']') - xSpaceOpt - } - xToken('>') - this.dtd = new DTD { - /*override var*/ externalID = extID - /*override val */decls = handle.decls.reverse - } - //this.dtd.initializeEntities(); - if (doc ne null) - doc.dtd = this.dtd - - handle.endDTD(n) - } - - def element(pscope: NamespaceBinding): NodeSeq = { - xToken('<') - element1(pscope) - } - - /** {{{ - * '<' element ::= xmlTag1 '>' { xmlExpr | '{' simpleExpr '}' } ETag - * | xmlTag1 '/' '>' - * }}} */ - def element1(pscope: NamespaceBinding): NodeSeq = { - val pos = this.pos - val (qname, (aMap, scope)) = xTag(pscope) - val (pre, local) = Utility.prefix(qname) match { - case Some(p) => (p, qname drop p.length+1) - case _ => (null, qname) - } - val ts = { - if (ch == '/') { // empty element - xToken("/>") - handle.elemStart(pos, pre, local, aMap, scope) - NodeSeq.Empty - } - else { // element with content - xToken('>') - handle.elemStart(pos, pre, local, aMap, scope) - val tmp = content(scope) - xEndTag(qname) - tmp - } - } - val res = handle.elem(pos, pre, local, aMap, scope, ts == NodeSeq.Empty, ts) - handle.elemEnd(pos, pre, local) - res - } - - /** Parse character data. - * - * precondition: `xEmbeddedBlock == false` (we are not in a scala block) - */ - private def xText: String = { - var exit = false - while (! exit) { - putChar(ch) - val opos = pos - nextch - - exit = eof || ( ch == '<' ) || ( ch == '&' ) - } - val str = cbuf.toString - cbuf.length = 0 - str - } - - /** attribute value, terminated by either ' or ". value may not contain <. - * {{{ - * AttValue ::= `'` { _ } `'` - * | `"` { _ } `"` - * }}} */ - def systemLiteral(): String = { - val endch = ch - if (ch != '\'' && ch != '"') - reportSyntaxError("quote ' or \" expected"); - nextch - while (ch != endch && !eof) { - putChar(ch) - nextch - } - nextch - val str = cbuf.toString() - cbuf.length = 0 - str - } - - /** {{{ - * [12] PubidLiteral ::= '"' PubidChar* '"' | "'" (PubidChar - "'")* "'" - * }}} */ - def pubidLiteral(): String = { - val endch = ch - if (ch!='\'' && ch != '"') - reportSyntaxError("quote ' or \" expected"); - nextch - while (ch != endch && !eof) { - putChar(ch) - //println("hello '"+ch+"'"+isPubIDChar(ch)) - if (!isPubIDChar(ch)) - reportSyntaxError("char '"+ch+"' is not allowed in public id") - nextch - } - nextch - val str = cbuf.toString - cbuf.length = 0 - str - } - - // - // dtd parsing - // - - def extSubset(): Unit = { - var textdecl: (Option[String],Option[String]) = null - if (ch == '<') { - nextch - if (ch == '?') { - nextch - textdecl = textDecl() - } else - markupDecl1() - } - while (!eof) - markupDecl() - } - - def markupDecl1() = { - def doInclude() = { - xToken('['); while(']' != ch) markupDecl(); nextch // ']' - } - def doIgnore() = { - xToken('['); while(']' != ch) nextch; nextch // ']' - } - if ('?' == ch) { - nextch - xProcInstr // simply ignore processing instructions! - } else { - xToken('!') - ch match { - case '-' => - xComment // ignore comments - - case 'E' => - nextch - if ('L' == ch) { - nextch - elementDecl() - } else - entityDecl() - - case 'A' => - nextch - attrDecl() - - case 'N' => - nextch - notationDecl() - - case '[' if inpStack.length >= extIndex => - nextch - xSpaceOpt - ch match { - case '%' => - nextch - val ent = xName - xToken(';') - xSpaceOpt - - push(ent) - xSpaceOpt - val stmt = xName - xSpaceOpt - - stmt match { - // parameter entity - case "INCLUDE" => doInclude() - case "IGNORE" => doIgnore() - } - case 'I' => - nextch - ch match { - case 'G' => - nextch - xToken("NORE") - xSpaceOpt - doIgnore() - case 'N' => - nextch - xToken("NCLUDE") - doInclude() - } - } - xToken(']') - xToken('>') - - case _ => - curInput.reportError(pos, "unexpected character '"+ch+"', expected some markupdecl") - while (ch!='>') - nextch - } - } - } - - def markupDecl(): Unit = ch match { - case '%' => // parameter entity reference - nextch - val ent = xName - xToken(';') - if (!isValidating) - handle.peReference(ent) // n-v: just create PE-reference - else - push(ent) // v: parse replacementText - - //peReference - case '<' => - nextch - markupDecl1() - case _ if isSpace(ch) => - xSpace - case _ => - reportSyntaxError("markupdecl: unexpected character '"+ch+"' #" + ch.toInt) - nextch - } - - /** "rec-xml/#ExtSubset" pe references may not occur within markup declarations - */ - def intSubset() { - //Console.println("(DEBUG) intSubset()") - xSpace - while (']' != ch) - markupDecl() - } - - /** <! element := ELEMENT - */ - def elementDecl() { - xToken("EMENT") - xSpace - val n = xName - xSpace - while ('>' != ch) { - //Console.println("["+ch+"]") - putChar(ch) - nextch - } - //Console.println("END["+ch+"]") - nextch - val cmstr = cbuf.toString() - cbuf.length = 0 - handle.elemDecl(n, cmstr) - } - - /** {{{ - * <! attlist := ATTLIST - * }}} */ - def attrDecl() = { - xToken("TTLIST") - xSpace - val n = xName - xSpace - var attList: List[AttrDecl] = Nil - - // later: find the elemDecl for n - while ('>' != ch) { - val aname = xName - xSpace - // could be enumeration (foo,bar) parse this later :-/ - while ('"' != ch && '\'' != ch && '#' != ch && '<' != ch) { - if (!isSpace(ch)) - cbuf.append(ch) - nextch - } - val atpe = cbuf.toString - cbuf.length = 0 - - val defdecl: DefaultDecl = ch match { - case '\'' | '"' => - DEFAULT(false, xAttributeValue()) - - case '#' => - nextch - xName match { - case "FIXED" => xSpace ; DEFAULT(true, xAttributeValue()) - case "IMPLIED" => IMPLIED - case "REQUIRED" => REQUIRED - } - case _ => - null - } - xSpaceOpt - - attList ::= AttrDecl(aname, atpe, defdecl) - cbuf.length = 0 - } - nextch - handle.attListDecl(n, attList.reverse) - } - - /** {{{ - * <! element := ELEMENT - * }}} */ - def entityDecl() = { - var isParameterEntity = false - var entdef: EntityDef = null - xToken("NTITY") - xSpace - if ('%' == ch) { - nextch - isParameterEntity = true - xSpace - } - val n = xName - xSpace - ch match { - case 'S' | 'P' => //sy - val extID = externalID() - if (isParameterEntity) { - xSpaceOpt - xToken('>') - handle.parameterEntityDecl(n, ExtDef(extID)) - } else { // notation? - xSpace - if ('>' != ch) { - xToken("NDATA") - xSpace - val notat = xName - xSpaceOpt - xToken('>') - handle.unparsedEntityDecl(n, extID, notat) - } else { - nextch - handle.parsedEntityDecl(n, ExtDef(extID)) - } - } - - case '"' | '\'' => - val av = xEntityValue() - xSpaceOpt - xToken('>') - if (isParameterEntity) - handle.parameterEntityDecl(n, IntDef(av)) - else - handle.parsedEntityDecl(n, IntDef(av)) - } - {} - } // entityDecl - - /** {{{ - * 'N' notationDecl ::= "OTATION" - * }}} */ - def notationDecl() { - xToken("OTATION") - xSpace - val notat = xName - xSpace - val extID = if (ch == 'S') { - externalID() - } - else if (ch == 'P') { - /** PublicID (without system, only used in NOTATION) */ - nextch - xToken("UBLIC") - xSpace - val pubID = pubidLiteral() - xSpaceOpt - val sysID = if (ch != '>') - systemLiteral() - else - null; - new PublicID(pubID, sysID) - } else { - reportSyntaxError("PUBLIC or SYSTEM expected"); - scala.sys.error("died parsing notationdecl") - } - xSpaceOpt - xToken('>') - handle.notationDecl(notat, extID) - } - - def reportSyntaxError(pos: Int, str: String) { curInput.reportError(pos, str) } - def reportSyntaxError(str: String) { reportSyntaxError(pos, str) } - def reportValidationError(pos: Int, str: String) { reportSyntaxError(pos, str) } - - def push(entityName: String) { - if (!eof) - inpStack = curInput :: inpStack - - // can't push before getting next character if needed - ch - - curInput = replacementText(entityName) - nextch - } - - def pushExternal(systemId: String) { - if (!eof) - inpStack = curInput :: inpStack - - // can't push before getting next character if needed - ch - - curInput = externalSource(systemId) - nextch - } - - def pop() { - curInput = inpStack.head - inpStack = inpStack.tail - lastChRead = curInput.ch - nextChNeeded = false - pos = curInput.pos - reachedEof = false // must be false, because of places where entity refs occur - } -} diff --git a/src/library/scala/xml/parsing/MarkupParserCommon.scala b/src/library/scala/xml/parsing/MarkupParserCommon.scala deleted file mode 100644 index da640484e0..0000000000 --- a/src/library/scala/xml/parsing/MarkupParserCommon.scala +++ /dev/null @@ -1,260 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala.xml -package parsing - -import scala.io.Source -import scala.xml.dtd._ -import scala.annotation.switch -import Utility.Escapes.{ pairs => unescape } - -import Utility.SU - -/** This is not a public trait - it contains common code shared - * between the library level XML parser and the compiler's. - * All members should be accessed through those. - */ -private[scala] trait MarkupParserCommon extends TokenTests { - protected def unreachable = scala.sys.error("Cannot be reached.") - - // type HandleType // MarkupHandler, SymbolicXMLBuilder - type InputType // Source, CharArrayReader - type PositionType // Int, Position - type ElementType // NodeSeq, Tree - type NamespaceType // NamespaceBinding, Any - type AttributesType // (MetaData, NamespaceBinding), mutable.Map[String, Tree] - - def mkAttributes(name: String, pscope: NamespaceType): AttributesType - def mkProcInstr(position: PositionType, name: String, text: String): ElementType - - /** parse a start or empty tag. - * [40] STag ::= '<' Name { S Attribute } [S] - * [44] EmptyElemTag ::= '<' Name { S Attribute } [S] - */ - protected def xTag(pscope: NamespaceType): (String, AttributesType) = { - val name = xName - xSpaceOpt - - (name, mkAttributes(name, pscope)) - } - - /** '<?' ProcInstr ::= Name [S ({Char} - ({Char}'>?' {Char})]'?>' - * - * see [15] - */ - def xProcInstr: ElementType = { - val n = xName - xSpaceOpt - xTakeUntil(mkProcInstr(_, n, _), () => tmppos, "?>") - } - - /** attribute value, terminated by either `'` or `"`. value may not contain `<`. - @param endCh either `'` or `"` - */ - def xAttributeValue(endCh: Char): String = { - val buf = new StringBuilder - while (ch != endCh) { - // well-formedness constraint - if (ch == '<') return errorAndResult("'<' not allowed in attrib value", "") - else if (ch == SU) truncatedError("") - else buf append ch_returning_nextch - } - ch_returning_nextch - // @todo: normalize attribute value - buf.toString - } - - def xAttributeValue(): String = { - val str = xAttributeValue(ch_returning_nextch) - // well-formedness constraint - normalizeAttributeValue(str) - } - - private def takeUntilChar(it: Iterator[Char], end: Char): String = { - val buf = new StringBuilder - while (it.hasNext) it.next match { - case `end` => return buf.toString - case ch => buf append ch - } - scala.sys.error("Expected '%s'".format(end)) - } - - /** [42] '<' xmlEndTag ::= '<' '/' Name S? '>' - */ - def xEndTag(startName: String) { - xToken('/') - if (xName != startName) - errorNoEnd(startName) - - xSpaceOpt - xToken('>') - } - - /** actually, Name ::= (Letter | '_' | ':') (NameChar)* but starting with ':' cannot happen - * Name ::= (Letter | '_') (NameChar)* - * - * see [5] of XML 1.0 specification - * - * pre-condition: ch != ':' // assured by definition of XMLSTART token - * post-condition: name does neither start, nor end in ':' - */ - def xName: String = { - if (ch == SU) - truncatedError("") - else if (!isNameStart(ch)) - return errorAndResult("name expected, but char '%s' cannot start a name" format ch, "") - - val buf = new StringBuilder - - do buf append ch_returning_nextch - while (isNameChar(ch)) - - if (buf.last == ':') { - reportSyntaxError( "name cannot end in ':'" ) - buf.toString dropRight 1 - } - else buf.toString - } - - private def attr_unescape(s: String) = s match { - case "lt" => "<" - case "gt" => ">" - case "amp" => "&" - case "apos" => "'" - case "quot" => "\"" - case "quote" => "\"" - case _ => "&" + s + ";" - } - - /** Replaces only character references right now. - * see spec 3.3.3 - */ - private def normalizeAttributeValue(attval: String): String = { - val buf = new StringBuilder - val it = attval.iterator.buffered - - while (it.hasNext) buf append (it.next match { - case ' ' | '\t' | '\n' | '\r' => " " - case '&' if it.head == '#' => it.next ; xCharRef(it) - case '&' => attr_unescape(takeUntilChar(it, ';')) - case c => c - }) - - buf.toString - } - - /** CharRef ::= "&#" '0'..'9' {'0'..'9'} ";" - * | "&#x" '0'..'9'|'A'..'F'|'a'..'f' { hexdigit } ";" - * - * see [66] - */ - def xCharRef(ch: () => Char, nextch: () => Unit): String = - Utility.parseCharRef(ch, nextch, reportSyntaxError _, truncatedError _) - - def xCharRef(it: Iterator[Char]): String = { - var c = it.next - Utility.parseCharRef(() => c, () => { c = it.next }, reportSyntaxError _, truncatedError _) - } - - def xCharRef: String = xCharRef(() => ch, () => nextch) - - /** Create a lookahead reader which does not influence the input */ - def lookahead(): BufferedIterator[Char] - - /** The library and compiler parsers had the interesting distinction of - * different behavior for nextch (a function for which there are a total - * of two plausible behaviors, so we know the design space was fully - * explored.) One of them returned the value of nextch before the increment - * and one of them the new value. So to unify code we have to at least - * temporarily abstract over the nextchs. - */ - def ch: Char - def nextch(): Unit - protected def ch_returning_nextch: Char - def eof: Boolean - - // def handle: HandleType - var tmppos: PositionType - - def xHandleError(that: Char, msg: String): Unit - def reportSyntaxError(str: String): Unit - def reportSyntaxError(pos: Int, str: String): Unit - - def truncatedError(msg: String): Nothing - def errorNoEnd(tag: String): Nothing - - protected def errorAndResult[T](msg: String, x: T): T = { - reportSyntaxError(msg) - x - } - - def xToken(that: Char) { - if (ch == that) nextch - else xHandleError(that, "'%s' expected instead of '%s'".format(that, ch)) - } - def xToken(that: Seq[Char]) { that foreach xToken } - - /** scan [S] '=' [S]*/ - def xEQ() = { xSpaceOpt; xToken('='); xSpaceOpt } - - /** skip optional space S? */ - def xSpaceOpt() = while (isSpace(ch) && !eof) nextch - - /** scan [3] S ::= (#x20 | #x9 | #xD | #xA)+ */ - def xSpace() = - if (isSpace(ch)) { nextch; xSpaceOpt } - else xHandleError(ch, "whitespace expected") - - /** Apply a function and return the passed value */ - def returning[T](x: T)(f: T => Unit): T = { f(x); x } - - /** Execute body with a variable saved and restored after execution */ - def saving[A, B](getter: A, setter: A => Unit)(body: => B): B = { - val saved = getter - try body - finally setter(saved) - } - - /** Take characters from input stream until given String "until" - * is seen. Once seen, the accumulated characters are passed - * along with the current Position to the supplied handler function. - */ - protected def xTakeUntil[T]( - handler: (PositionType, String) => T, - positioner: () => PositionType, - until: String): T = - { - val sb = new StringBuilder - val head = until.head - val rest = until.tail - - while (true) { - if (ch == head && peek(rest)) - return handler(positioner(), sb.toString) - else if (ch == SU) - truncatedError("") // throws TruncatedXMLControl in compiler - - sb append ch - nextch - } - unreachable - } - - /** Create a non-destructive lookahead reader and see if the head - * of the input would match the given String. If yes, return true - * and drop the entire String from input; if no, return false - * and leave input unchanged. - */ - private def peek(lookingFor: String): Boolean = - (lookahead() take lookingFor.length sameElements lookingFor.iterator) && { - // drop the chars from the real reader (all lookahead + orig) - (0 to lookingFor.length) foreach (_ => nextch) - true - } -} diff --git a/src/library/scala/xml/parsing/NoBindingFactoryAdapter.scala b/src/library/scala/xml/parsing/NoBindingFactoryAdapter.scala deleted file mode 100644 index 22dd450072..0000000000 --- a/src/library/scala/xml/parsing/NoBindingFactoryAdapter.scala +++ /dev/null @@ -1,36 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - -package scala.xml -package parsing - -import factory.NodeFactory - -/** nobinding adaptor providing callbacks to parser to create elements. -* implements hash-consing -*/ -class NoBindingFactoryAdapter extends FactoryAdapter with NodeFactory[Elem] -{ - /** True. Every XML node may contain text that the application needs */ - def nodeContainsText(label: String) = true - - /** From NodeFactory. Constructs an instance of scala.xml.Elem */ - protected def create(pre: String, label: String, attrs: MetaData, scope: NamespaceBinding, children: Seq[Node]): Elem = - Elem(pre, label, attrs, scope, children: _*) - - /** From FactoryAdapter. Creates a node. never creates the same node twice, using hash-consing. */ - def createNode(pre: String, label: String, attrs: MetaData, scope: NamespaceBinding, children: List[Node]): Elem = - Elem(pre, label, attrs, scope, children: _*) - - /** Creates a text node. */ - def createText(text: String) = Text(text) - - /** Creates a processing instruction. */ - def createProcInstr(target: String, data: String) = makeProcInstr(target, data) -} diff --git a/src/library/scala/xml/parsing/TokenTests.scala b/src/library/scala/xml/parsing/TokenTests.scala deleted file mode 100644 index c9cafaeea1..0000000000 --- a/src/library/scala/xml/parsing/TokenTests.scala +++ /dev/null @@ -1,100 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala.xml -package parsing - -/** - * Helper functions for parsing XML fragments - */ -trait TokenTests { - - /** {{{ - * (#x20 | #x9 | #xD | #xA) - * }}} */ - final def isSpace(ch: Char): Boolean = ch match { - case '\u0009' | '\u000A' | '\u000D' | '\u0020' => true - case _ => false - } - /** {{{ - * (#x20 | #x9 | #xD | #xA)+ - * }}} */ - final def isSpace(cs: Seq[Char]): Boolean = cs.nonEmpty && (cs forall isSpace) - - /** These are 99% sure to be redundant but refactoring on the safe side. */ - def isAlpha(c: Char) = (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') - def isAlphaDigit(c: Char) = isAlpha(c) || (c >= '0' && c <= '9') - - /** {{{ - * NameChar ::= Letter | Digit | '.' | '-' | '_' | ':' - * | CombiningChar | Extender - * }}} - * See [4] and Appendix B of XML 1.0 specification. - */ - def isNameChar(ch: Char) = { - import java.lang.Character._ - // The constants represent groups Mc, Me, Mn, Lm, and Nd. - - isNameStart(ch) || (getType(ch).toByte match { - case COMBINING_SPACING_MARK | - ENCLOSING_MARK | NON_SPACING_MARK | - MODIFIER_LETTER | DECIMAL_DIGIT_NUMBER => true - case _ => ".-:" contains ch - }) - } - - /** {{{ - * NameStart ::= ( Letter | '_' ) - * }}} - * where Letter means in one of the Unicode general - * categories `{ Ll, Lu, Lo, Lt, Nl }`. - * - * We do not allow a name to start with `:`. - * See [3] and Appendix B of XML 1.0 specification - */ - def isNameStart(ch: Char) = { - import java.lang.Character._ - - getType(ch).toByte match { - case LOWERCASE_LETTER | - UPPERCASE_LETTER | OTHER_LETTER | - TITLECASE_LETTER | LETTER_NUMBER => true - case _ => ch == '_' - } - } - - /** {{{ - * Name ::= ( Letter | '_' ) (NameChar)* - * }}} - * See [5] of XML 1.0 specification. - */ - def isName(s: String) = - s.nonEmpty && isNameStart(s.head) && (s.tail forall isNameChar) - - def isPubIDChar(ch: Char): Boolean = - isAlphaDigit(ch) || (isSpace(ch) && ch != '\u0009') || - ("""-\()+,./:=?;!*#@$_%""" contains ch) - - /** - * Returns `true` if the encoding name is a valid IANA encoding. - * This method does not verify that there is a decoder available - * for this encoding, only that the characters are valid for an - * IANA encoding name. - * - * @param ianaEncoding The IANA encoding name. - */ - def isValidIANAEncoding(ianaEncoding: Seq[Char]) = { - def charOK(c: Char) = isAlphaDigit(c) || ("._-" contains c) - - ianaEncoding.nonEmpty && isAlpha(ianaEncoding.head) && - (ianaEncoding.tail forall charOK) - } - - def checkSysID(s: String) = List('"', '\'') exists (c => !(s contains c)) - def checkPubID(s: String) = s forall isPubIDChar -} diff --git a/src/library/scala/xml/parsing/ValidatingMarkupHandler.scala b/src/library/scala/xml/parsing/ValidatingMarkupHandler.scala deleted file mode 100644 index 0edea043a5..0000000000 --- a/src/library/scala/xml/parsing/ValidatingMarkupHandler.scala +++ /dev/null @@ -1,119 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - - -package scala.xml -package parsing - -import scala.xml.dtd._ -import scala.util.logging.Logged - -abstract class ValidatingMarkupHandler extends MarkupHandler with Logged { - - var rootLabel:String = _ - var qStack: List[Int] = Nil - var qCurrent: Int = -1 - - var declStack: List[ElemDecl] = Nil - var declCurrent: ElemDecl = null - - final override val isValidating = true - - override def log(msg: String) {} - - /* - override def checkChildren(pos: Int, pre: String, label:String,ns:NodeSeq): Unit = { - Console.println("checkChildren()"); - val decl = lookupElemDecl(label); - // @todo: nice error message - val res = decl.contentModel.validate(ns); - Console.println("res = "+res); - if(!res) - //sys.error("invalid!"); - } - */ - - override def endDTD(n:String) = { - rootLabel = n - } - override def elemStart(pos: Int, pre: String, label: String, attrs: MetaData, scope:NamespaceBinding) { - - def advanceDFA(dm:DFAContentModel) = { - val trans = dm.dfa.delta(qCurrent) - log("advanceDFA(dm): " + dm) - log("advanceDFA(trans): " + trans) - trans.get(ContentModel.ElemName(label)) match { - case Some(qNew) => qCurrent = qNew - case _ => reportValidationError(pos, "DTD says, wrong element, expected one of "+trans.keys); - } - } - // advance in current automaton - log("[qCurrent = "+qCurrent+" visiting "+label+"]") - - if (qCurrent == -1) { // root - log(" checking root") - if (label != rootLabel) - reportValidationError(pos, "this element should be "+rootLabel) - } else { - log(" checking node") - declCurrent.contentModel match { - case ANY => - case EMPTY => - reportValidationError(pos, "DTD says, no elems, no text allowed here") - case PCDATA => - reportValidationError(pos, "DTD says, no elements allowed here") - case m @ MIXED(r) => - advanceDFA(m) - case e @ ELEMENTS(r) => - advanceDFA(e) - } - } - // push state, decl - qStack = qCurrent :: qStack - declStack = declCurrent :: declStack - - declCurrent = lookupElemDecl(label) - qCurrent = 0 - log(" done now") - } - - override def elemEnd(pos: Int, pre: String, label: String) { - log(" elemEnd") - qCurrent = qStack.head - qStack = qStack.tail - declCurrent = declStack.head - declStack = declStack.tail - log(" qCurrent now" + qCurrent) - log(" declCurrent now" + declCurrent) - } - - final override def elemDecl(name: String, cmstr: String) { - decls = ElemDecl(name, ContentModel.parse(cmstr)) :: decls - } - - final override def attListDecl(name: String, attList: List[AttrDecl]) { - decls = AttListDecl(name, attList) :: decls - } - - final override def unparsedEntityDecl(name: String, extID: ExternalID, notat: String) { - decls = UnparsedEntityDecl(name, extID, notat) :: decls - } - - final override def notationDecl(notat: String, extID: ExternalID) { - decls = NotationDecl(notat, extID) :: decls; - } - - final override def peReference(name: String) { - decls = PEReference(name) :: decls - } - - /** report a syntax error */ - def reportValidationError(pos: Int, str: String): Unit - -} diff --git a/src/library/scala/xml/parsing/XhtmlEntities.scala b/src/library/scala/xml/parsing/XhtmlEntities.scala deleted file mode 100644 index 1bb843818a..0000000000 --- a/src/library/scala/xml/parsing/XhtmlEntities.scala +++ /dev/null @@ -1,53 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala.xml -package parsing - -import scala.xml.dtd.{ IntDef, ParsedEntityDecl } - -/** - * @author (c) David Pollak 2007 WorldWide Conferencing, LLC. - * - */ -object XhtmlEntities { - val entList = List(("quot",34), ("amp",38), ("lt",60), ("gt",62), ("nbsp",160), ("iexcl",161), ("cent",162), ("pound",163), ("curren",164), ("yen",165), - ("euro",8364), ("brvbar",166), ("sect",167), ("uml",168), ("copy",169), ("ordf",170), ("laquo",171), ("shy",173), ("reg",174), ("trade",8482), - ("macr",175), ("deg",176), ("plusmn",177), ("sup2",178), ("sup3",179), ("acute",180), ("micro",181), ("para",182), ("middot",183), ("cedil",184), - ("sup1",185), ("ordm",186), ("raquo",187), ("frac14",188), ("frac12",189), ("frac34",190), ("iquest",191), ("times",215), ("divide",247), - ("Agrave",192), ("Aacute",193), ("Acirc",194), ("Atilde",195), ("Auml",196), ("Aring",197), ("AElig",198), ("Ccedil",199), ("Egrave",200), - ("Eacute",201), ("Ecirc",202), ("Euml",203), ("Igrave",204), ("Iacute",205), ("Icirc",206), ("Iuml",207), ("ETH",208), ("Ntilde",209), - ("Ograve",210), ("Oacute",211), ("Ocirc",212), ("Otilde",213), ("Ouml",214), ("Oslash",216), ("Ugrave",217), ("Uacute",218), ("Ucirc",219), - ("Uuml",220), ("Yacute",221), ("THORN",222), ("szlig",223), ("agrave",224), ("aacute",225), ("acirc",226), ("atilde",227), ("auml",228), - ("aring",229), ("aelig",230), ("ccedil",231), ("egrave",232), ("eacute",233), ("ecirc",234), ("euml",235), ("igrave",236), ("iacute",237), - ("icirc",238), ("iuml",239), ("eth",240), ("ntilde",241), ("ograve",242), ("oacute",243), ("ocirc",244), ("otilde",245), ("ouml",246), - ("oslash",248), ("ugrave",249), ("uacute",250), ("ucirc",251), ("uuml",252), ("yacute",253), ("thorn",254), ("yuml",255), ("OElig",338), - ("oelig",339), ("Scaron",352), ("scaron",353), ("Yuml",376), ("circ",710), ("ensp",8194), ("emsp",8195), ("zwnj",204), ("zwj",8205), ("lrm",8206), - ("rlm",8207), ("ndash",8211), ("mdash",8212), ("lsquo",8216), ("rsquo",8217), ("sbquo",8218), ("ldquo",8220), ("rdquo",8221), ("bdquo",8222), - ("dagger",8224), ("Dagger",8225), ("permil",8240), ("lsaquo",8249), ("rsaquo",8250), ("fnof",402), ("bull",8226), ("hellip",8230), ("prime",8242), - ("Prime",8243), ("oline",8254), ("frasl",8260), ("weierp",8472), ("image",8465), ("real",8476), ("alefsym",8501), ("larr",8592), ("uarr",8593), - ("rarr",8594), ("darr",8495), ("harr",8596), ("crarr",8629), ("lArr",8656), ("uArr",8657), ("rArr",8658), ("dArr",8659), ("hArr",8660), - ("forall",8704), ("part",8706), ("exist",8707), ("empty",8709), ("nabla",8711), ("isin",8712), ("notin",8713), ("ni",8715), ("prod",8719), - ("sum",8721), ("minus",8722), ("lowast",8727), ("radic",8730), ("prop",8733), ("infin",8734), ("ang",8736), ("and",8743), ("or",8744), - ("cap",8745), ("cup",8746), ("int",8747), ("there4",8756), ("sim",8764), ("cong",8773), ("asymp",8776), ("ne",8800), ("equiv",8801), ("le",8804), - ("ge",8805), ("sub",8834), ("sup",8835), ("nsub",8836), ("sube",8838), ("supe",8839), ("oplus",8853), ("otimes",8855), ("perp",8869), ("sdot",8901), - ("lceil",8968), ("rceil",8969), ("lfloor",8970), ("rfloor",8971), ("lang",9001), ("rang",9002), ("loz",9674), ("spades",9824), ("clubs",9827), - ("hearts",9829), ("diams",9830), ("Alpha",913), ("Beta",914), ("Gamma",915), ("Delta",916), ("Epsilon",917), ("Zeta",918), ("Eta",919), - ("Theta",920), ("Iota",921), ("Kappa",922), ("Lambda",923), ("Mu",924), ("Nu",925), ("Xi",926), ("Omicron",927), ("Pi",928), ("Rho",929), - ("Sigma",931), ("Tau",932), ("Upsilon",933), ("Phi",934), ("Chi",935), ("Psi",936), ("Omega",937), ("alpha",945), ("beta",946), ("gamma",947), - ("delta",948), ("epsilon",949), ("zeta",950), ("eta",951), ("theta",952), ("iota",953), ("kappa",954), ("lambda",955), ("mu",956), ("nu",957), - ("xi",958), ("omicron",959), ("pi",960), ("rho",961), ("sigmaf",962), ("sigma",963), ("tau",964), ("upsilon",965), ("phi",966), ("chi",967), - ("psi",968), ("omega",969), ("thetasym",977), ("upsih",978), ("piv",982)) - - val entMap: Map[String, Char] = Map.empty[String, Char] ++ entList.map { case (name, value) => (name, value.toChar)} - - val entities = entList. - map { case (name, value) => (name, new ParsedEntityDecl(name, new IntDef(value.toChar.toString)))} - - def apply() = entities -} diff --git a/src/library/scala/xml/parsing/XhtmlParser.scala b/src/library/scala/xml/parsing/XhtmlParser.scala deleted file mode 100644 index d08cb1fa9c..0000000000 --- a/src/library/scala/xml/parsing/XhtmlParser.scala +++ /dev/null @@ -1,30 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala.xml -package parsing - -import scala.io.Source - -/** An XML Parser that preserves `CDATA` blocks and knows about - * [[scala.xml.parsing.XhtmlEntities]]. - * - * @author (c) David Pollak, 2007 WorldWide Conferencing, LLC. - */ -class XhtmlParser(val input: Source) extends ConstructingHandler with MarkupParser with ExternalSources { - val preserveWS = true - ent ++= XhtmlEntities() -} - -/** Convenience method that instantiates, initializes and runs an `XhtmlParser`. - * - * @author Burak Emir - */ -object XhtmlParser { - def apply(source: Source): NodeSeq = new XhtmlParser(source).initialize.document -} diff --git a/src/library/scala/xml/persistent/CachedFileStorage.scala b/src/library/scala/xml/persistent/CachedFileStorage.scala deleted file mode 100644 index 916a1a0cf7..0000000000 --- a/src/library/scala/xml/persistent/CachedFileStorage.scala +++ /dev/null @@ -1,125 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala.xml -package persistent - -import java.io.{ File, FileOutputStream } -import java.nio.ByteBuffer -import java.nio.channels.Channels -import java.lang.Thread -import scala.util.logging.Logged -import scala.collection.Iterator - -/** Mutable storage of immutable xml trees. Everything is kept in memory, - * with a thread periodically checking for changes and writing to file. - * - * To ensure atomicity, two files are used, `filename1` and `'$'+filename1`. - * The implementation switches between the two, deleting the older one - * after a complete dump of the database has been written. - * - * @author Burak Emir - */ -abstract class CachedFileStorage(private val file1: File) extends Thread with Logged { - - private val file2 = new File(file1.getParent, file1.getName+"$") - - /** Either equals `file1` or `file2`, references the next file in which - * updates will be stored. - */ - private var theFile: File = null - - private def switch() = { theFile = if (theFile == file1) file2 else file1; } - - /** this storage modified since last modification check */ - protected var dirty = false - - /** period between modification checks, in milliseconds */ - protected val interval = 1000 - - /** finds and loads the storage file. subclasses should call this method - * prior to any other, but only once, to obtain the initial sequence of nodes. - */ - protected def initialNodes: Iterator[Node] = (file1.exists, file2.exists) match { - case (false,false) => - theFile = file1 - Iterator.empty - case (true, true ) if (file1.lastModified < file2.lastModified) => - theFile = file2 - load - case (true, _ ) => - theFile = file1 - load - case _ => - theFile = file2 - load - } - - /** returns an iterator over the nodes in this storage */ - def nodes: Iterator[Node] - - /** adds a node, setting this.dirty to true as a side effect */ - def += (e: Node): Unit - - /** removes a tree, setting this.dirty to true as a side effect */ - def -= (e: Node): Unit - - /* loads and parses XML from file */ - private def load: Iterator[Node] = { - import scala.io.Source - import scala.xml.parsing.ConstructingParser - log("[load]\nloading "+theFile) - val src = Source.fromFile(theFile) - log("parsing "+theFile) - val res = ConstructingParser.fromSource(src,false).document.docElem(0) - switch - log("[load done]") - res.child.iterator - } - - /** saves the XML to file */ - private def save() = if (this.dirty) { - log("[save]\ndeleting "+theFile) - theFile.delete() - log("creating new "+theFile) - theFile.createNewFile() - val fos = new FileOutputStream(theFile) - val c = fos.getChannel() - - // @todo: optimize - val storageNode = <nodes>{ nodes.toList }</nodes> - val w = Channels.newWriter(c, "utf-8") - XML.write(w, storageNode, "utf-8", true, null) - - log("writing to "+theFile) - - w.close - c.close - fos.close - dirty = false - switch - log("[save done]") - } - - /** Run method of the thread. remember to use `start()` to start a thread, - * not `run`. */ - override def run = { - log("[run]\nstarting storage thread, checking every "+interval+" ms") - while (true) { - Thread.sleep( this.interval ) - save - } - } - - /** Force writing of contents to the file, even if there has not been any - * update. */ - def flush() = { - this.dirty = true - save - } -} diff --git a/src/library/scala/xml/persistent/Index.scala b/src/library/scala/xml/persistent/Index.scala deleted file mode 100644 index defaf67d52..0000000000 --- a/src/library/scala/xml/persistent/Index.scala +++ /dev/null @@ -1,16 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - - -package scala.xml -package persistent - -/** an Index returns some unique key that is part of a node - */ -abstract class Index[A] extends Function1[Node,A] {} diff --git a/src/library/scala/xml/persistent/SetStorage.scala b/src/library/scala/xml/persistent/SetStorage.scala deleted file mode 100644 index 20a5bb6767..0000000000 --- a/src/library/scala/xml/persistent/SetStorage.scala +++ /dev/null @@ -1,43 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - -package scala.xml -package persistent - -import scala.collection.mutable -import java.io.File - -/** A persistent store with set semantics. This class allows to add and remove - * trees, but never contains two structurally equal trees. - * - * @author Burak Emir - */ -class SetStorage(file: File) extends CachedFileStorage(file) { - - private var theSet: mutable.HashSet[Node] = new mutable.HashSet[Node] - - // initialize - - { - val it = super.initialNodes - dirty = it.hasNext - for(x <- it) { - theSet += x; - } - } - - /* forwarding methods to hashset*/ - - def += (e: Node): Unit = synchronized { this.dirty = true; theSet += e } - - def -= (e: Node): Unit = synchronized { this.dirty = true; theSet -= e } - - def nodes = synchronized { theSet.iterator } - -} diff --git a/src/library/scala/xml/pull/XMLEvent.scala b/src/library/scala/xml/pull/XMLEvent.scala deleted file mode 100644 index a266380f87..0000000000 --- a/src/library/scala/xml/pull/XMLEvent.scala +++ /dev/null @@ -1,59 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - - -package scala.xml -package pull - -/** An XML event for pull parsing. All events received during - * parsing will be one of the subclasses of this trait. - */ -trait XMLEvent - -/** - * An Element's start tag was encountered. - * @param pre prefix, if any, on the element. This is the `xs` in `<xs:string>foo</xs:string>`. - * @param label the name of the element, not including the prefix - * @param attrs any attributes on the element - */ -case class EvElemStart(pre: String, label: String, attrs: MetaData, scope: NamespaceBinding) extends XMLEvent - -/** - * An Element's end tag was encountered. - * @param pre prefix, if any, on the element. This is the `xs` in `<xs:string>foo</xs:string>`. - * @param label the name of the element, not including the prefix - */ -case class EvElemEnd(pre: String, label: String) extends XMLEvent - -/** - * A text node was encountered. - * @param text the text that was found - */ -case class EvText(text: String) extends XMLEvent - -/** An entity reference was encountered. - * @param entity the name of the entity, e.g. `gt` when encountering the entity `>` - */ -case class EvEntityRef(entity: String) extends XMLEvent - -/** - * A processing instruction was encountered. - * @param target the "PITarget" of the processing instruction. For the instruction `<?foo bar="baz"?>`, the target would - * be `foo` - * @param text the remainder of the instruction. For the instruction `<?foo bar="baz"?>`, the text would - * be `bar="baz"` - * @see [[http://www.w3.org/TR/REC-xml/#sec-pi]] - */ -case class EvProcInstr(target: String, text: String) extends XMLEvent - -/** - * A comment was encountered - * @param text the text of the comment - */ -case class EvComment(text: String) extends XMLEvent diff --git a/src/library/scala/xml/pull/XMLEventReader.scala b/src/library/scala/xml/pull/XMLEventReader.scala deleted file mode 100755 index 428c305055..0000000000 --- a/src/library/scala/xml/pull/XMLEventReader.scala +++ /dev/null @@ -1,156 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala.xml -package pull - -import scala.io.Source -import java.lang.Thread -import java.util.concurrent.LinkedBlockingQueue -import java.nio.channels.ClosedChannelException -import scala.xml.parsing.{ ExternalSources, MarkupHandler, MarkupParser } - -/** - * Main entry point into creating an event-based XML parser. Treating this - * as a [[scala.collection.Iterator]] will provide access to the generated events. - * @param src A [[scala.io.Source]] for XML data to parse - * - * @author Burak Emir - * @author Paul Phillips - */ -class XMLEventReader(src: Source) -extends scala.collection.AbstractIterator[XMLEvent] - with ProducerConsumerIterator[XMLEvent] { - - // We implement a pull parser as an iterator, but since we may be operating on - // a stream (e.g. XML over a network) there may be arbitrarily long periods when - // the queue is empty. Fortunately the ProducerConsumerIterator is ideally - // suited to this task, possibly because it was written for use by this class. - - // to override as necessary - val preserveWS = true - - override val MaxQueueSize = 1000 - protected case object POISON extends XMLEvent - val EndOfStream = POISON - - // thread machinery - private[this] val parser = new Parser(src) - private[this] val parserThread = new Thread(parser, "XMLEventReader") - parserThread.start - // enqueueing the poison object is the reliable way to cause the - // iterator to terminate; hasNext will return false once it sees it. - // Calling interrupt() on the parserThread is the only way we can get - // it to stop producing tokens since it's lost deep in document() - - // we cross our fingers the interrupt() gets to its target, but if it - // fails for whatever reason the iterator correctness is not impacted, - // only performance (because it will finish the entire XML document, - // or at least as much as it can fit in the queue.) - def stop() = { - produce(POISON) - parserThread.interrupt() - } - - private class Parser(val input: Source) extends MarkupHandler with MarkupParser with ExternalSources with Runnable { - val preserveWS = XMLEventReader.this.preserveWS - // track level for elem memory usage optimization - private var level = 0 - - // this is Parser's way to add to the queue - the odd return type - // is to conform to MarkupHandler's interface - def setEvent(es: XMLEvent*): NodeSeq = { - es foreach produce - NodeSeq.Empty - } - - override def elemStart(pos: Int, pre: String, label: String, attrs: MetaData, scope: NamespaceBinding) { - level += 1 - setEvent(EvElemStart(pre, label, attrs, scope)) - } - override def elemEnd(pos: Int, pre: String, label: String) { - setEvent(EvElemEnd(pre, label)) - level -= 1 - } - - // this is a dummy to satisfy MarkupHandler's API - // memory usage optimization return one <ignore/> for top level to satisfy - // MarkupParser.document() otherwise NodeSeq.Empty - private var ignoreWritten = false - final def elem(pos: Int, pre: String, label: String, attrs: MetaData, pscope: NamespaceBinding, empty: Boolean, nodes: NodeSeq): NodeSeq = - if (level == 1 && !ignoreWritten) {ignoreWritten = true; <ignore/> } else NodeSeq.Empty - - def procInstr(pos: Int, target: String, txt: String) = setEvent(EvProcInstr(target, txt)) - def comment(pos: Int, txt: String) = setEvent(EvComment(txt)) - def entityRef(pos: Int, n: String) = setEvent(EvEntityRef(n)) - def text(pos: Int, txt:String) = setEvent(EvText(txt)) - - override def run() { - curInput = input - interruptibly { this.initialize.document() } - setEvent(POISON) - } - } -} - -// An iterator designed for one or more producers to generate -// elements, and a single consumer to iterate. Iteration will continue -// until closeIterator() is called, after which point producers -// calling produce() will receive interruptions. -// -// Since hasNext may block indefinitely if nobody is producing, -// there is also an available() method which will return true if -// the next call hasNext is guaranteed not to block. -// -// This is not thread-safe for multiple consumers! -trait ProducerConsumerIterator[T >: Null] extends Iterator[T] { - // abstract - iterator-specific distinguished object for marking eos - val EndOfStream: T - - // defaults to unbounded - override to positive Int if desired - val MaxQueueSize = -1 - - def interruptibly[T](body: => T): Option[T] = try Some(body) catch { - case _: InterruptedException => Thread.currentThread.interrupt(); None - case _: ClosedChannelException => None - } - - private[this] lazy val queue = - if (MaxQueueSize < 0) new LinkedBlockingQueue[T]() - else new LinkedBlockingQueue[T](MaxQueueSize) - private[this] var buffer: T = _ - private def fillBuffer() = { - buffer = interruptibly(queue.take) getOrElse EndOfStream - isElement(buffer) - } - private def isElement(x: T) = x != null && x != EndOfStream - private def eos() = buffer == EndOfStream - - // public producer interface - this is the only method producers call, so - // LinkedBlockingQueue's synchronization is all we need. - def produce(x: T): Unit = if (!eos) interruptibly(queue put x) - - // consumer/iterator interface - we need not synchronize access to buffer - // because we required there to be only one consumer. - def hasNext = !eos && (buffer != null || fillBuffer) - - def next() = { - if (eos) throw new NoSuchElementException("ProducerConsumerIterator") - if (buffer == null) fillBuffer - - drainBuffer - } - - def available() = isElement(buffer) || isElement(queue.peek) - - private def drainBuffer() = { - assert(!eos) - val res = buffer - buffer = null - res - } -} diff --git a/src/library/scala/xml/pull/package.scala b/src/library/scala/xml/pull/package.scala deleted file mode 100644 index 3742c55513..0000000000 --- a/src/library/scala/xml/pull/package.scala +++ /dev/null @@ -1,41 +0,0 @@ -package scala.xml - -/** - * Classes needed to view an XML document as a series of events. The document - * is parsed by an [[scala.xml.pull.XMLEventReader]] instance. You can treat it as - * an [[scala.collection.Iterator]] to retrieve the events, which are all - * subclasses of [[scala.xml.pull.XMLEvent]]. - * - * {{{ - * scala> val source = Source.fromString("""<?xml version="1.0" encoding="UTF-8" standalone="yes"?> - * <?instruction custom value="customvalue"?> - * <!DOCTYPE foo [ - * <!ENTITY bar "BAR"> - * ]><foo>Hello<!-- this is a comment --><bar>&bar;</bar><bar>></bar></foo>""") - * - * source: scala.io.Source = non-empty iterator - * - * scala> val reader = new XMLEventReader(source) - * reader: scala.xml.pull.XMLEventReader = non-empty iterator - * - * scala> reader.foreach{ println(_) } - * EvProcInstr(instruction,custom value="customvalue") - * EvText( - * ) - * EvElemStart(null,foo,,) - * EvText(Hello) - * EvComment( this is a comment ) - * EvElemStart(null,bar,,) - * EvText(BAR) - * EvElemEnd(null,bar) - * EvElemStart(null,bar,,) - * EvEntityRef(gt) - * EvElemEnd(null,bar) - * EvElemEnd(null,foo) - * EvText( - * - * ) - * - * }}} - */ -package object pull diff --git a/src/library/scala/xml/transform/BasicTransformer.scala b/src/library/scala/xml/transform/BasicTransformer.scala deleted file mode 100644 index 1402ccd6aa..0000000000 --- a/src/library/scala/xml/transform/BasicTransformer.scala +++ /dev/null @@ -1,59 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - - -package scala.xml -package transform - -/** A class for XML transformations. - * - * @author Burak Emir - * @version 1.0 - */ -abstract class BasicTransformer extends Function1[Node,Node] -{ - protected def unchanged(n: Node, ns: Seq[Node]) = - ns.length == 1 && (ns.head == n) - - /** Call transform(Node) for each node in ns, append results - * to NodeBuffer. - */ - def transform(it: Iterator[Node], nb: NodeBuffer): Seq[Node] = - it.foldLeft(nb)(_ ++= transform(_)).toSeq - - /** Call transform(Node) to each node in ns, yield ns if nothing changes, - * otherwise a new sequence of concatenated results. - */ - def transform(ns: Seq[Node]): Seq[Node] = { - val (xs1, xs2) = ns span (n => unchanged(n, transform(n))) - - if (xs2.isEmpty) ns - else xs1 ++ transform(xs2.head) ++ transform(xs2.tail) - } - - def transform(n: Node): Seq[Node] = { - if (n.doTransform) n match { - case Group(xs) => Group(transform(xs)) // un-group the hack Group tag - case _ => - val ch = n.child - val nch = transform(ch) - - if (ch eq nch) n - else Elem(n.prefix, n.label, n.attributes, n.scope, nch: _*) - } - else n - } - - def apply(n: Node): Node = { - val seq = transform(n) - if (seq.length > 1) - throw new UnsupportedOperationException("transform must return single node for root"); - else seq.head - } -} diff --git a/src/library/scala/xml/transform/RewriteRule.scala b/src/library/scala/xml/transform/RewriteRule.scala deleted file mode 100644 index 1dca495a10..0000000000 --- a/src/library/scala/xml/transform/RewriteRule.scala +++ /dev/null @@ -1,27 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - - -package scala.xml -package transform - -/** a RewriteRule, when applied to a term, yields either - * the resulting of rewriting or the term itself it the rule - * is not applied. - * - * @author Burak Emir - * @version 1.0 - */ -abstract class RewriteRule extends BasicTransformer { - /** a name for this rewrite rule */ - val name = this.toString() - override def transform(ns: Seq[Node]): Seq[Node] = super.transform(ns) - override def transform(n: Node): Seq[Node] = n -} - diff --git a/src/library/scala/xml/transform/RuleTransformer.scala b/src/library/scala/xml/transform/RuleTransformer.scala deleted file mode 100644 index 85e92e5773..0000000000 --- a/src/library/scala/xml/transform/RuleTransformer.scala +++ /dev/null @@ -1,17 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - - -package scala.xml -package transform - -class RuleTransformer(rules: RewriteRule*) extends BasicTransformer { - override def transform(n: Node): Seq[Node] = - rules.foldLeft(super.transform(n)) { (res, rule) => rule transform res } -} |