summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--build.xml2
-rw-r--r--src/compiler/scala/tools/nsc/doc/html/page/Template.scala7
-rw-r--r--src/library/scala/collection/BitSetLike.scala13
-rw-r--r--src/library/scala/collection/immutable/Range.scala7
-rw-r--r--src/library/scala/util/parsing/combinator/Parsers.scala70
-rw-r--r--test/files/neg/t3481.check29
-rw-r--r--test/files/neg/t3481.scala28
-rw-r--r--test/files/run/parserFilter.check9
-rw-r--r--test/files/run/parserFilter.scala15
-rw-r--r--test/files/run/parserForFilter.check1
-rw-r--r--test/files/run/parserForFilter.scala12
-rw-r--r--test/files/run/parserNoSuccessMessage.check20
-rw-r--r--test/files/run/parserNoSuccessMessage.scala19
-rw-r--r--test/files/run/t4658.check80
-rw-r--r--test/files/run/t4658.scala41
15 files changed, 337 insertions, 16 deletions
diff --git a/build.xml b/build.xml
index 1694ba8b7a..d7c523a618 100644
--- a/build.xml
+++ b/build.xml
@@ -202,6 +202,8 @@ INITIALISATION
============================================================================ -->
<target name="init">
+ <available file="${lib.dir}/scala-library.jar" property="starr.present"/>
+ <fail unless="starr.present" message="Could not find STARR. Have your run the pull-binary-libs.sh script?"/>
<!-- scalac.args.optimise is selectively overridden in certain antcall tasks. -->
<property name="scalac.args.optimise" value=""/>
<!-- scalac.args.quickonly are added to quick.* targets but not others (particularly, locker.)
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 813958af85..5e5320ca9a 100644
--- a/src/compiler/scala/tools/nsc/doc/html/page/Template.scala
+++ b/src/compiler/scala/tools/nsc/doc/html/page/Template.scala
@@ -563,8 +563,7 @@ 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
@@ -580,8 +579,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/library/scala/collection/BitSetLike.scala b/src/library/scala/collection/BitSetLike.scala
index 7d9f48f299..e4f9fd436a 100644
--- a/src/library/scala/collection/BitSetLike.scala
+++ b/src/library/scala/collection/BitSetLike.scala
@@ -65,7 +65,7 @@ trait BitSetLike[+This <: BitSetLike[This] with SortedSet[Int]] extends SortedSe
var i = nwords
while (i > 0) {
i -= 1
- s += popCount(word(i))
+ s += java.lang.Long.bitCount(word(i))
}
s
}
@@ -221,15 +221,4 @@ object BitSetLike {
else assert(w == 0L)
newelems
}
-
- private val pc1: Array[Int] = {
- def countBits(x: Int): Int = if (x == 0) 0 else x % 2 + countBits(x >>> 1)
- Array.tabulate(256)(countBits _)
- }
-
- private def popCount(w: Long): Int = {
- def pc2(w: Int) = if (w == 0) 0 else pc1(w & 0xff) + pc1(w >>> 8)
- def pc4(w: Int) = if (w == 0) 0 else pc2(w & 0xffff) + pc2(w >>> 16)
- if (w == 0L) 0 else pc4(w.toInt) + pc4((w >>> 32).toInt)
- }
}
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/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
diff --git a/test/files/neg/t3481.check b/test/files/neg/t3481.check
new file mode 100644
index 0000000000..48e6ff357b
--- /dev/null
+++ b/test/files/neg/t3481.check
@@ -0,0 +1,29 @@
+t3481.scala:5: error: type mismatch;
+ found : String("hello")
+ required: _$1 where type +_$1
+ f[A[Int]]("hello")
+ ^
+t3481.scala:11: error: type mismatch;
+ found : _$2 where type +_$2
+ required: b.T
+ (which expands to) _$2
+ def f[T <: B[_]](a: T#T, b: T) = b.m(a)
+ ^
+t3481.scala:12: error: type mismatch;
+ found : String("Hello")
+ required: _$2 where type +_$2
+ f("Hello", new B[Int])
+ ^
+t3481.scala:18: error: type mismatch;
+ found : String("Hello")
+ required: t3481.ex3.b.T2
+ (which expands to) _$3
+ b.m("Hello")
+ ^
+t3481.scala:25: error: type mismatch;
+ found : String("Hello")
+ required: t3481.ex4.Test.b.T2
+ (which expands to) _$4
+ b.m("Hello")
+ ^
+5 errors found
diff --git a/test/files/neg/t3481.scala b/test/files/neg/t3481.scala
new file mode 100644
index 0000000000..f4b781ee37
--- /dev/null
+++ b/test/files/neg/t3481.scala
@@ -0,0 +1,28 @@
+object t3481 {
+ object ex1 {
+ trait A[T] { type B = T }
+ def f[T <: A[_]](a: T#B) = 1
+ f[A[Int]]("hello")
+ }
+
+ object ex2 {
+ trait A { type T; def m(t: T) = t.toString }
+ class B[T2] extends A { type T = T2 }
+ def f[T <: B[_]](a: T#T, b: T) = b.m(a)
+ f("Hello", new B[Int])
+ }
+
+ object ex3 {
+ class B[T] { type T2 = T; def m(t: T2) = t.toString }
+ val b: B[_] = new B[Int]
+ b.m("Hello")
+ }
+
+ object ex4 {
+ abstract class B[T] { type T2 = T; def m(t: T2): Any }
+ object Test {
+ val b: B[_] = sys.error("")
+ b.m("Hello")
+ }
+ }
+} \ No newline at end of file
diff --git a/test/files/run/parserFilter.check b/test/files/run/parserFilter.check
new file mode 100644
index 0000000000..be04454426
--- /dev/null
+++ b/test/files/run/parserFilter.check
@@ -0,0 +1,9 @@
+[1.3] failure: Input doesn't match filter: false
+
+if false
+ ^
+[1.1] failure: Input doesn't match filter: not
+
+not true
+^
+[1.8] parsed: (if~true)
diff --git a/test/files/run/parserFilter.scala b/test/files/run/parserFilter.scala
new file mode 100644
index 0000000000..d007d441f4
--- /dev/null
+++ b/test/files/run/parserFilter.scala
@@ -0,0 +1,15 @@
+object Test extends scala.util.parsing.combinator.RegexParsers {
+ val keywords = Set("if", "false")
+ def word: Parser[String] = "\\w+".r
+
+ def keyword: Parser[String] = word filter (keywords.contains)
+ def ident: Parser[String] = word filter(!keywords.contains(_))
+
+ def test = keyword ~ ident
+
+ def main(args: Array[String]) {
+ println(parseAll(test, "if false"))
+ println(parseAll(test, "not true"))
+ println(parseAll(test, "if true"))
+ }
+}
diff --git a/test/files/run/parserForFilter.check b/test/files/run/parserForFilter.check
new file mode 100644
index 0000000000..a53c147719
--- /dev/null
+++ b/test/files/run/parserForFilter.check
@@ -0,0 +1 @@
+[1.13] parsed: (second,first)
diff --git a/test/files/run/parserForFilter.scala b/test/files/run/parserForFilter.scala
new file mode 100644
index 0000000000..1bc44f8033
--- /dev/null
+++ b/test/files/run/parserForFilter.scala
@@ -0,0 +1,12 @@
+object Test extends scala.util.parsing.combinator.RegexParsers {
+ def word: Parser[String] = "\\w+".r
+
+ def twoWords = for {
+ (a ~ b) <- word ~ word
+ } yield (b, a)
+
+ def main(args: Array[String]) {
+ println(parseAll(twoWords, "first second"))
+ }
+}
+
diff --git a/test/files/run/parserNoSuccessMessage.check b/test/files/run/parserNoSuccessMessage.check
new file mode 100644
index 0000000000..fe00d2fd3a
--- /dev/null
+++ b/test/files/run/parserNoSuccessMessage.check
@@ -0,0 +1,20 @@
+[1.2] failure: string matching regex `\d+' expected but `x' found
+
+-x
+ ^
+[1.1] failure: string matching regex `\d+' expected but `x' found
+
+x
+^
+[1.3] parsed: (Some(-)~5)
+[1.2] parsed: (None~5)
+[1.2] error: Number expected!
+
+-x
+ ^
+[1.1] error: Number expected!
+
+x
+^
+[1.3] parsed: (Some(-)~5)
+[1.2] parsed: (None~5)
diff --git a/test/files/run/parserNoSuccessMessage.scala b/test/files/run/parserNoSuccessMessage.scala
new file mode 100644
index 0000000000..93aa252db0
--- /dev/null
+++ b/test/files/run/parserNoSuccessMessage.scala
@@ -0,0 +1,19 @@
+object Test extends scala.util.parsing.combinator.RegexParsers {
+ def sign = "-"
+ def number = "\\d+".r
+ def p = sign.? ~ number withErrorMessage "Number expected!"
+ def q = sign.? ~! number withErrorMessage "Number expected!"
+
+ def main(args: Array[String]) {
+ println(parseAll(p, "-x"))
+ println(parseAll(p, "x"))
+ println(parseAll(p, "-5"))
+ println(parseAll(p, "5"))
+ println(parseAll(q, "-x"))
+ println(parseAll(q, "x"))
+ println(parseAll(q, "-5"))
+ println(parseAll(q, "5"))
+ }
+}
+
+
diff --git a/test/files/run/t4658.check b/test/files/run/t4658.check
new file mode 100644
index 0000000000..743b0faee3
--- /dev/null
+++ b/test/files/run/t4658.check
@@ -0,0 +1,80 @@
+Ranges:
+1073741824
+1073741824
+0
+0
+55
+25
+1
+-45
+-55
+0
+-24
+-30
+0
+-40
+-55
+-10
+-24
+-30
+-10
+IntRanges:
+Disabled #1
+Disabled #2
+0
+0
+55
+25
+1
+-45
+-55
+0
+-24
+-30
+0
+-40
+-55
+-10
+-24
+-30
+-10
+LongRanges:
+Disabled #1
+Disabled #2
+0
+0
+55
+25
+1
+-45
+-55
+0
+-24
+-30
+0
+-40
+-55
+-10
+-24
+-30
+-10
+BigIntRanges:
+Disabled #1
+Disabled #2
+0
+0
+55
+25
+1
+-45
+-55
+0
+-24
+-30
+0
+-40
+-55
+-10
+-24
+-30
+-10
diff --git a/test/files/run/t4658.scala b/test/files/run/t4658.scala
new file mode 100644
index 0000000000..e1799fae9b
--- /dev/null
+++ b/test/files/run/t4658.scala
@@ -0,0 +1,41 @@
+import scala.collection.immutable.NumericRange
+//#4658
+object Test {
+
+ case class R(start: Int, end: Int, step: Int = 1, inclusive: Boolean = true)
+
+ val rangeData = Array(
+ R(1, Int.MaxValue), R(-Int.MaxValue, -1), R(0, 0), R(0,0, inclusive = false), R(1,10),
+ R(1,10,2), R(1,10,11), R(-10, -5), R(-10, 0), R(-10, 10), R(-10, -5, 2), R(-10, 0, 2), R(-10, 10, 2),
+ R(-10, -5, inclusive = false), R(-10, 0, inclusive = false), R(-10, 10, inclusive = false),
+ R(-10, -5, 2, inclusive = false), R(-10, 0, 2, inclusive = false), R(-10, 10, 2, inclusive = false)
+ )
+
+ def ranges = rangeData.map(r => if (r.inclusive) r.start to r.end by r.step else r.start until r.end by r.step)
+
+ def numericIntRanges = rangeData.map(r => if (r.inclusive) NumericRange.inclusive(r.start, r.end, r.step) else NumericRange(r.start, r.end, r.step))
+
+ def numericLongRanges = rangeData.map(r => if (r.inclusive) NumericRange.inclusive(r.start.toLong, r.end, r.step) else NumericRange(r.start.toLong, r.end, r.step))
+
+ def numericBigIntRanges = rangeData.map(r => if (r.inclusive) NumericRange.inclusive(BigInt(r.start), BigInt(r.end), BigInt(r.step)) else NumericRange(BigInt(r.start), BigInt(r.end), BigInt(r.step)))
+
+ def main(args: Array[String]) {
+ // We drop the first two tests for all ranges which don't have a decent sum implementation,
+ // because it is just too slow.
+ println("Ranges:")
+ ranges.foreach{range => println(range.sum)}
+ println("IntRanges:")
+ println("Disabled #1")
+ println("Disabled #2")
+ numericIntRanges.drop(2).foreach{range => println(range.sum)}
+ println("LongRanges:")
+ println("Disabled #1")
+ println("Disabled #2")
+ numericLongRanges.drop(2).foreach{range => println(range.sum)}
+ println("BigIntRanges:")
+ println("Disabled #1")
+ println("Disabled #2")
+ numericBigIntRanges.drop(2).foreach{range => println(range.sum)}
+ }
+
+} \ No newline at end of file