summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2011-12-04 17:43:10 -0800
committerPaul Phillips <paulp@improving.org>2011-12-04 17:43:10 -0800
commit1ed57a4c19f89bc6736271fd63d465fed405c4d3 (patch)
tree3a5d7d3d91e326682486bac2acc19c4917381b25 /src
parent261c63995ccf6a238786fd3c31796be7a965fec4 (diff)
parenta289465c70630719cbd3a74edf5502a156ef83c4 (diff)
downloadscala-1ed57a4c19f89bc6736271fd63d465fed405c4d3.tar.gz
scala-1ed57a4c19f89bc6736271fd63d465fed405c4d3.tar.bz2
scala-1ed57a4c19f89bc6736271fd63d465fed405c4d3.zip
Merge branch 'master' into xsbt
Diffstat (limited to 'src')
-rw-r--r--src/compiler/scala/reflect/internal/Importers.scala2
-rw-r--r--src/compiler/scala/reflect/internal/Types.scala10
-rw-r--r--src/compiler/scala/tools/nsc/ast/Trees.scala4
-rw-r--r--src/compiler/scala/tools/nsc/doc/html/page/Template.scala7
-rw-r--r--src/compiler/scala/tools/nsc/transform/LiftCode.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Contexts.scala17
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala44
-rw-r--r--src/compiler/scala/tools/util/EditDistance.scala54
-rw-r--r--src/continuations/plugin/scala/tools/selectivecps/CPSUtils.scala2
-rw-r--r--src/continuations/plugin/scala/tools/selectivecps/SelectiveCPSPlugin.scala19
-rw-r--r--src/library/scala/Enumeration.scala64
-rw-r--r--src/library/scala/collection/GenSeqLike.scala4
-rw-r--r--src/library/scala/collection/TraversableLike.scala4
-rw-r--r--src/library/scala/collection/immutable/Range.scala7
-rw-r--r--src/library/scala/math/package.scala12
-rw-r--r--src/library/scala/util/parsing/combinator/Parsers.scala70
16 files changed, 261 insertions, 61 deletions
diff --git a/src/compiler/scala/reflect/internal/Importers.scala b/src/compiler/scala/reflect/internal/Importers.scala
index 6d672d9263..60b353a7c4 100644
--- a/src/compiler/scala/reflect/internal/Importers.scala
+++ b/src/compiler/scala/reflect/internal/Importers.scala
@@ -231,6 +231,8 @@ trait Importers { self: SymbolTable =>
new PackageDef(importRefTree(pid), stats map importTree)
case from.ModuleDef(mods, name, impl) =>
new ModuleDef(importModifiers(mods), importName(name).toTermName, importTemplate(impl))
+ case from.emptyValDef =>
+ emptyValDef
case from.ValDef(mods, name, tpt, rhs) =>
new ValDef(importModifiers(mods), importName(name).toTermName, importTree(tpt), importTree(rhs))
case from.DefDef(mods, name, tparams, vparamss, tpt, rhs) =>
diff --git a/src/compiler/scala/reflect/internal/Types.scala b/src/compiler/scala/reflect/internal/Types.scala
index 320fb949ff..265261f594 100644
--- a/src/compiler/scala/reflect/internal/Types.scala
+++ b/src/compiler/scala/reflect/internal/Types.scala
@@ -4174,8 +4174,16 @@ A type's typeSymbol should never be inspected directly.
private def adaptToNewRun(pre: Type, sym: Symbol): Symbol = {
if (phase.flatClasses) {
sym
+ } else if (sym == definitions.RootClass) {
+ definitions.RootClass
+ } else if (sym == definitions.RootPackage) {
+ definitions.RootPackage
} else if (sym.isModuleClass) {
- adaptToNewRun(pre, sym.sourceModule).moduleClass
+ val sourceModule1 = adaptToNewRun(pre, sym.sourceModule)
+ val result = sourceModule1.moduleClass
+ val msg = "sym = %s, sourceModule = %s, sourceModule.moduleClass = %s => sourceModule1 = %s, sourceModule1.moduleClass = %s"
+ assert(result != NoSymbol, msg.format(sym, sym.sourceModule, sym.sourceModule.moduleClass, sourceModule1, sourceModule1.moduleClass))
+ result
} else if ((pre eq NoPrefix) || (pre eq NoType) || sym.isPackageClass) {
sym
} else {
diff --git a/src/compiler/scala/tools/nsc/ast/Trees.scala b/src/compiler/scala/tools/nsc/ast/Trees.scala
index 9668debbbb..85849cfad4 100644
--- a/src/compiler/scala/tools/nsc/ast/Trees.scala
+++ b/src/compiler/scala/tools/nsc/ast/Trees.scala
@@ -257,6 +257,10 @@ trait Trees extends reflect.internal.Trees { self: Global =>
case _: DefTree | Function(_, _) | Template(_, _, _) =>
resetDef(tree)
tree.tpe = null
+ tree match {
+ case tree: DefDef => tree.tpt.tpe = null
+ case _ => ()
+ }
case tpt: TypeTree =>
if (tpt.wasEmpty) tree.tpe = null
case This(_) if tree.symbol != null && tree.symbol.isPackageClass =>
diff --git a/src/compiler/scala/tools/nsc/doc/html/page/Template.scala b/src/compiler/scala/tools/nsc/doc/html/page/Template.scala
index 5e5320ca9a..813958af85 100644
--- a/src/compiler/scala/tools/nsc/doc/html/page/Template.scala
+++ b/src/compiler/scala/tools/nsc/doc/html/page/Template.scala
@@ -563,7 +563,8 @@ class Template(tpl: DocTemplateEntity) extends HtmlPage {
if (!nameLink.isEmpty)
<a href={nameLink}>{nameHtml}</a>
else nameHtml
- }{
+ }
+ {
def tparamsToHtml(mbr: Entity): NodeSeq = mbr match {
case hk: HigherKinded =>
val tpss = hk.typeParams
@@ -579,8 +580,8 @@ class Template(tpl: DocTemplateEntity) extends HtmlPage {
case _ => NodeSeq.Empty
}
tparamsToHtml(mbr)
- }{
- if (isReduced) NodeSeq.Empty else {
+ }
+ { if (isReduced) NodeSeq.Empty else {
def paramsToHtml(vlsss: List[List[ValueParam]]): NodeSeq = {
def param0(vl: ValueParam): NodeSeq =
// notice the }{ in the next lines, they are necessary to avoid a undesired withspace in output
diff --git a/src/compiler/scala/tools/nsc/transform/LiftCode.scala b/src/compiler/scala/tools/nsc/transform/LiftCode.scala
index 7a64fc9b5e..68a53e57a1 100644
--- a/src/compiler/scala/tools/nsc/transform/LiftCode.scala
+++ b/src/compiler/scala/tools/nsc/transform/LiftCode.scala
@@ -475,7 +475,7 @@ abstract class LiftCode extends Transform with TypingTransformers {
case tt: TypeTree if (tt.tpe != null) =>
if (!(boundSyms exists (tt.tpe contains _))) mirrorCall("TypeTree", reifyType(tt.tpe))
else if (tt.original != null) reify(tt.original)
- else TypeTree()
+ else mirrorCall("TypeTree")
case global.emptyValDef =>
mirrorSelect("emptyValDef")
case _ =>
diff --git a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
index d252281002..1d9eb9c292 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
@@ -17,13 +17,16 @@ import annotation.tailrec
trait Contexts { self: Analyzer =>
import global._
- val NoContext = new Context {
- override def implicitss: List[List[ImplicitInfo]] = List()
- outer = this
+ object NoContext extends Context {
+ outer = this
+ enclClass = this
+ enclMethod = this
+
+ override def nextEnclosing(p: Context => Boolean): Context = this
+ override def enclosingContextChain: List[Context] = Nil
+ override def implicitss: List[List[ImplicitInfo]] = Nil
override def toString = "NoContext"
}
- NoContext.enclClass = NoContext
- NoContext.enclMethod = NoContext
private val startContext = {
NoContext.make(
@@ -337,7 +340,9 @@ trait Contexts { self: Analyzer =>
}
def nextEnclosing(p: Context => Boolean): Context =
- if (this == NoContext || p(this)) this else outer.nextEnclosing(p)
+ if (p(this)) this else outer.nextEnclosing(p)
+
+ def enclosingContextChain: List[Context] = this :: outer.enclosingContextChain
override def toString = "Context(%s@%s unit=%s scope=%s)".format(
owner.fullName, tree.shortClass, unit, scope.##
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index b969e9629f..7671ccbed7 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -19,6 +19,7 @@ import symtab.Flags._
import util.Statistics
import util.Statistics._
import scala.tools.util.StringOps.{ countAsString, countElementsAsString }
+import scala.tools.util.EditDistance.similarString
// Suggestion check whether we can do without priming scopes with symbols of outer scopes,
// like the IDE does.
@@ -3457,12 +3458,10 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
if (treeInfo.isVariableOrGetter(qual1)) {
stopTimer(failedOpEqNanos, opeqStart)
convertToAssignment(fun, qual1, name, args, ex)
- } else {
+ }
+ else {
stopTimer(failedApplyNanos, appStart)
- if ((qual1.symbol ne null) && qual1.symbol.isValue)
- error(tree.pos, "reassignment to val")
- else
- reportTypeError(fun.pos, ex)
+ reportTypeError(fun.pos, ex)
setError(tree)
}
case _ =>
@@ -3754,7 +3753,11 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
defSym = EmptyPackageClass.tpe.nonPrivateMember(name)
defSym != NoSymbol
}
-
+ def startingIdentContext = (
+ // ignore current variable scope in patterns to enforce linearity
+ if ((mode & (PATTERNmode | TYPEPATmode)) == 0) context
+ else context.outer
+ )
// A symbol qualifies if it exists and is not stale. Stale symbols
// are made to disappear here. In addition,
// if we are in a constructor of a pattern, we ignore all definitions
@@ -3770,13 +3773,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
if (defSym == NoSymbol) {
var defEntry: ScopeEntry = null // the scope entry of defSym, if defined in a local scope
- var cx = context
- if ((mode & (PATTERNmode | TYPEPATmode)) != 0) {
- // println("ignoring scope: "+name+" "+cx.scope+" "+cx.outer.scope)
- // ignore current variable scope in patterns to enforce linearity
- cx = cx.outer
- }
-
+ var cx = startingIdentContext
while (defSym == NoSymbol && cx != NoContext) {
currentRun.compileSourceFor(context.asInstanceOf[analyzer.Context], name)
pre = cx.enclClass.prefix
@@ -3874,7 +3871,26 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
if (inaccessibleSym eq NoSymbol) {
// Avoiding some spurious error messages: see SI-2388.
if (reporter.hasErrors && (name startsWith tpnme.ANON_CLASS_NAME)) ()
- else error(tree.pos, "not found: "+decodeWithKind(name, context.owner))
+ else {
+ val similar = (
+ // name length check to limit unhelpful suggestions for e.g. "x" and "b1"
+ if (name.length > 2) {
+ val allowed = (
+ startingIdentContext.enclosingContextChain
+ flatMap (ctx => ctx.scope.toList ++ ctx.imports.flatMap(_.allImportedSymbols))
+ filter (sym => sym.isTerm == name.isTermName)
+ filterNot (sym => sym.isPackage || sym.isSynthetic || sym.hasMeaninglessName)
+ )
+ val allowedStrings = (
+ allowed.map("" + _.name).distinct.sorted
+ filterNot (s => (s contains '$') || (s contains ' '))
+ )
+ similarString("" + name, allowedStrings)
+ }
+ else ""
+ )
+ error(tree.pos, "not found: "+decodeWithKind(name, context.owner) + similar)
+ }
}
else new AccessError(
tree, inaccessibleSym, context.enclClass.owner.thisType,
diff --git a/src/compiler/scala/tools/util/EditDistance.scala b/src/compiler/scala/tools/util/EditDistance.scala
new file mode 100644
index 0000000000..a8d7408532
--- /dev/null
+++ b/src/compiler/scala/tools/util/EditDistance.scala
@@ -0,0 +1,54 @@
+/* NSC -- new Scala compiler
+ * Copyright 2005-2011 LAMP/EPFL
+ * @author Paul Phillips
+ */
+
+package scala.tools
+package util
+
+object EditDistance {
+ def similarString(name: String, allowed: TraversableOnce[String]): String = {
+ val suggested = suggestions(name, allowed.toSeq, maxDistance = 1, maxSuggestions = 2)
+ if (suggested.isEmpty) ""
+ else suggested.mkString(" (similar: ", ", ", ")")
+ }
+
+ def suggestions(a: String, bs: Seq[String], maxDistance: Int, maxSuggestions: Int): Seq[String] = (
+ bs map (b => (b, distance(a, b)))
+ filter (_._2 <= maxDistance)
+ sortBy (_._2)
+ take (maxSuggestions)
+ map (_._1)
+ )
+
+ def distance(a: String, b: String): Int = levenshtein(a, b, transpositions = true)
+
+ def levenshtein(s: String, t: String, transpositions: Boolean): Int = {
+ val n = s.length
+ val m = t.length
+ if (n == 0) return m
+ if (m == 0) return n
+
+ val d = Array.ofDim[Int](n + 1, m + 1)
+ 0 to n foreach (x => d(x)(0) = x)
+ 0 to m foreach (x => d(0)(x) = x)
+
+ for (i <- 1 to n ; val s_i = s(i - 1) ; j <- 1 to m) {
+ val t_j = t(j - 1)
+ val cost = if (s_i == t_j) 0 else 1
+
+ val c1 = d(i - 1)(j) + 1
+ val c2 = d(i)(j - 1) + 1
+ val c3 = d(i - 1)(j - 1) + cost
+
+ d(i)(j) = c1 min c2 min c3
+
+ if (transpositions) {
+ if (i > 1 && j > 1 && s(i - 1) == t(j - 2) && s(i - 2) == t(j - 1))
+ d(i)(j) = d(i)(j) min (d(i - 2)(j - 2) + cost)
+ }
+ }
+
+ d(n)(m)
+ }
+}
diff --git a/src/continuations/plugin/scala/tools/selectivecps/CPSUtils.scala b/src/continuations/plugin/scala/tools/selectivecps/CPSUtils.scala
index 5cb06d42db..f4481b800e 100644
--- a/src/continuations/plugin/scala/tools/selectivecps/CPSUtils.scala
+++ b/src/continuations/plugin/scala/tools/selectivecps/CPSUtils.scala
@@ -9,7 +9,7 @@ trait CPSUtils {
import global._
import definitions._
- var cpsEnabled = false
+ var cpsEnabled = true
val verbose: Boolean = System.getProperty("cpsVerbose", "false") == "true"
def vprintln(x: =>Any): Unit = if (verbose) println(x)
diff --git a/src/continuations/plugin/scala/tools/selectivecps/SelectiveCPSPlugin.scala b/src/continuations/plugin/scala/tools/selectivecps/SelectiveCPSPlugin.scala
index 8a500d6c4d..eb18f03748 100644
--- a/src/continuations/plugin/scala/tools/selectivecps/SelectiveCPSPlugin.scala
+++ b/src/continuations/plugin/scala/tools/selectivecps/SelectiveCPSPlugin.scala
@@ -26,7 +26,6 @@ class SelectiveCPSPlugin(val global: Global) extends Plugin {
override val runsBefore = List("uncurry")
}
-
val components = List[PluginComponent](anfPhase, cpsPhase)
val checker = new CPSAnnotationChecker {
@@ -43,19 +42,17 @@ class SelectiveCPSPlugin(val global: Global) extends Plugin {
}
// TODO: require -enabled command-line flag
-
override def processOptions(options: List[String], error: String => Unit) = {
- var enabled = false
- for (option <- options) {
- if (option == "enable") {
- enabled = true
- } else {
- error("Option not understood: "+option)
- }
+ var enabled = true
+ options foreach {
+ case "enable" => enabled = true
+ case "disable" => enabled = false
+ case option => error("Option not understood: "+option)
}
setEnabled(enabled)
}
- override val optionsHelp: Option[String] =
- Some(" -P:continuations:enable Enable continuations")
+ override val optionsHelp: Option[String] = {
+ Some(" -P:continuations:disable Disable continuations plugin")
+ }
}
diff --git a/src/library/scala/Enumeration.scala b/src/library/scala/Enumeration.scala
index 07e758013c..c967a48abc 100644
--- a/src/library/scala/Enumeration.scala
+++ b/src/library/scala/Enumeration.scala
@@ -8,7 +8,7 @@
package scala
-import scala.collection.{ mutable, immutable, generic, SetLike, AbstractSet }
+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
@@ -53,10 +53,14 @@ import java.util.regex.Pattern
* @author Matthias Zenger
*/
@SerialVersionUID(8476000850333817230L)
-abstract class Enumeration(initial: Int, names: String*) extends Serializable {
+abstract class Enumeration(initial: Int,
+ @deprecated("Names should be specified individually or discovered via reflection", "2.10")
+ names: String*) extends Serializable {
thisenum =>
def this() = this(0)
+
+ @deprecated("Names should be specified individually or discovered via reflection", "2.10")
def this(names: String*) = this(0, names: _*)
/* Note that `readResolve` cannot be private, since otherwise
@@ -86,7 +90,7 @@ abstract class Enumeration(initial: Int, names: String*) extends Serializable {
*/
def values: ValueSet = {
if (!vsetDefined) {
- vset = new ValueSet(immutable.SortedSet.empty[Int] ++ (vmap.values map (_.id)))
+ vset = (ValueSet.newBuilder ++= vmap.values).result()
vsetDefined = true
}
vset
@@ -104,6 +108,10 @@ abstract class Enumeration(initial: Int, names: String*) extends Serializable {
* enumeration. */
private var topId = initial
+ /** The lowest integer amongst those used to identify values in this
+ * enumeration, but no higher than 0. */
+ private var bottomId = if(initial < 0) initial else 0
+
/** The highest integer amongst those used to identify values in this
* enumeration. */
final def maxId = topId
@@ -200,6 +208,9 @@ abstract class Enumeration(initial: Int, names: String*) extends Serializable {
case _ => false
}
override def hashCode: Int = id.##
+
+ /** Create a ValueSet which contains this value and another one */
+ def + (v: Value) = ValueSet(this, v)
}
/** A class implementing the [[scala.Enumeration.Value]] type. This class
@@ -217,6 +228,7 @@ abstract class Enumeration(initial: Int, names: String*) extends Serializable {
vsetDefined = false
nextId = i + 1
if (nextId > topId) topId = nextId
+ if (i < bottomId) bottomId = i
def id = i
override def toString() =
if (name != null) name
@@ -230,34 +242,56 @@ abstract class Enumeration(initial: Int, names: String*) extends Serializable {
}
}
+ /** An ordering by id for values of this set */
+ object ValueOrdering extends Ordering[Value] {
+ def compare(x: Value, y: Value): Int = x.id - y.id
+ }
+
/** A class for sets of values.
* Iterating through this set will yield values in increasing order of their ids.
*
- * @param ids The set of ids of values, organized as a `SortedSet`.
+ * @param nnIds The set of ids of values (adjusted so that the lowest value does
+ * not fall below zero), organized as a `BitSet`.
*/
- class ValueSet private[Enumeration] (val ids: immutable.SortedSet[Int])
+ class ValueSet private[ValueSet] (private[this] var nnIds: immutable.BitSet)
extends AbstractSet[Value]
- with Set[Value]
- with SetLike[Value, ValueSet] {
+ with immutable.SortedSet[Value]
+ with SortedSetLike[Value, ValueSet]
+ with Serializable {
+
+ implicit def ordering: Ordering[Value] = ValueOrdering
+ def rangeImpl(from: Option[Value], until: Option[Value]): ValueSet =
+ new ValueSet(nnIds.rangeImpl(from.map(_.id - bottomId), until.map(_.id - bottomId)))
override def empty = ValueSet.empty
- def contains(v: Value) = ids contains (v.id)
- def + (value: Value) = new ValueSet(ids + value.id)
- def - (value: Value) = new ValueSet(ids - value.id)
- def iterator = ids.iterator map thisenum.apply
+ 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))
override def stringPrefix = thisenum + ".ValueSet"
+ /** Creates a bit mask for the zero-adjusted ids in this set as a
+ * new array of longs */
+ def toBitMask: Array[Long] = nnIds.toBitMask
}
-
+
/** A factory object for value sets */
object ValueSet {
import generic.CanBuildFrom
/** The empty value set */
- val empty = new ValueSet(immutable.SortedSet.empty)
+ val empty = new ValueSet(immutable.BitSet.empty)
/** A value set consisting of given elements */
- def apply(elems: Value*): ValueSet = empty ++ elems
+ def apply(elems: Value*): ValueSet = (newBuilder ++= elems).result()
+ /** A value set containing all the values for the zero-adjusted ids
+ * corresponding to the bits in an array */
+ def fromBitMask(elems: Array[Long]): ValueSet = new ValueSet(immutable.BitSet.fromBitMask(elems))
/** A builder object for value sets */
- def newBuilder: mutable.Builder[Value, ValueSet] = new mutable.SetBuilder(empty)
+ 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 result() = new ValueSet(b.toImmutable)
+ }
/** The implicit builder for value sets */
implicit def canBuildFrom: CanBuildFrom[ValueSet, Value, ValueSet] =
new CanBuildFrom[ValueSet, Value, ValueSet] {
diff --git a/src/library/scala/collection/GenSeqLike.scala b/src/library/scala/collection/GenSeqLike.scala
index b3dd4764a9..63e9543711 100644
--- a/src/library/scala/collection/GenSeqLike.scala
+++ b/src/library/scala/collection/GenSeqLike.scala
@@ -276,6 +276,8 @@ trait GenSeqLike[+A, +Repr] extends GenIterableLike[A, Repr] with Equals with Pa
/** A copy of the $coll with an element prepended.
*
* Note that :-ending operators are right associative (see example).
+ * A mnemonic for `+:` vs. `:+` is: the COLon goes on the COLlection side.
+ *
* Also, the original $coll is not modified, so you will want to capture the result.
*
* Example:
@@ -304,6 +306,8 @@ trait GenSeqLike[+A, +Repr] extends GenIterableLike[A, Repr] with Equals with Pa
/** A copy of this $coll with an element appended.
*
+ * A mnemonic for `+:` vs. `:+` is: the COLon goes on the COLlection side.
+ *
* $willNotTerminateInf
* @param elem the appended element
* @tparam B the element type of the returned $coll.
diff --git a/src/library/scala/collection/TraversableLike.scala b/src/library/scala/collection/TraversableLike.scala
index 6fa05bd85b..4f0fec1de3 100644
--- a/src/library/scala/collection/TraversableLike.scala
+++ b/src/library/scala/collection/TraversableLike.scala
@@ -159,8 +159,10 @@ trait TraversableLike[+A, +Repr] extends HasNewBuilder[A, Repr]
/** As with `++`, returns a new collection containing the elements from the left operand followed by the
* elements from the right operand.
+ *
* It differs from `++` in that the right operand determines the type of
* the resulting collection rather than the left one.
+ * Mnemonic: the COLon is on the side of the new COLlection type.
*
* Example:
* {{{
@@ -195,8 +197,10 @@ trait TraversableLike[+A, +Repr] extends HasNewBuilder[A, Repr]
/** As with `++`, returns a new collection containing the elements from the
* left operand followed by the elements from the right operand.
+ *
* It differs from `++` in that the right operand determines the type of
* the resulting collection rather than the left one.
+ * Mnemonic: the COLon is on the side of the new COLlection type.
*
* Example:
* {{{
diff --git a/src/library/scala/collection/immutable/Range.scala b/src/library/scala/collection/immutable/Range.scala
index 47ce2f0341..3736096f36 100644
--- a/src/library/scala/collection/immutable/Range.scala
+++ b/src/library/scala/collection/immutable/Range.scala
@@ -211,6 +211,13 @@ extends collection.AbstractSeq[Int]
final def contains(x: Int) = isWithinBoundaries(x) && ((x - start) % step == 0)
+ final override def sum[B >: Int](implicit num: Numeric[B]): Int = {
+ val len = length
+ if (len == 0) 0
+ else if (len == 1) head
+ else (len.toLong * (head + last) / 2).toInt
+ }
+
override def toIterable = this
override def toSeq = this
diff --git a/src/library/scala/math/package.scala b/src/library/scala/math/package.scala
index 8948722340..0417461f85 100644
--- a/src/library/scala/math/package.scala
+++ b/src/library/scala/math/package.scala
@@ -127,15 +127,9 @@ package object math {
else if (x > 0) 1.0f
else x // NaN
- def signum(x: Long): Long =
- if (x == 0l) 0l
- else if (x < 0) -1l
- else 1l
-
- def signum(x: Int): Int =
- if (x == 0) 0
- else if (x < 0) -1
- else 1
+ def signum(x: Long): Long = java.lang.Long.signum(x)
+
+ def signum(x: Int): Int = java.lang.Integer.signum(x)
// -----------------------------------------------------------------------
// root functions
diff --git a/src/library/scala/util/parsing/combinator/Parsers.scala b/src/library/scala/util/parsing/combinator/Parsers.scala
index e7ea9f598b..751539243b 100644
--- a/src/library/scala/util/parsing/combinator/Parsers.scala
+++ b/src/library/scala/util/parsing/combinator/Parsers.scala
@@ -108,6 +108,8 @@ trait Parsers {
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
@@ -137,6 +139,10 @@ trait Parsers {
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
@@ -161,6 +167,8 @@ trait Parsers {
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 = sys.error("No result when parsing failed")
}
/** An extractor so `NoSuccess(msg, next)` can be used in matches. */
@@ -224,6 +232,12 @@ trait Parsers {
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(2, 9, "As of 2.9, the call-by-name argument is evaluated at most once per constructed Parser object, instead of on every need that arises during parsing.")
@@ -443,6 +457,62 @@ trait Parsers {
* @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