summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAntonio Cunei <antonio.cunei@epfl.ch>2011-04-21 09:39:19 +0000
committerAntonio Cunei <antonio.cunei@epfl.ch>2011-04-21 09:39:19 +0000
commitf5faa91d3d6ed21a2849f090c40082f95e7dc121 (patch)
tree9b180ee4335c67c5930b4d644054099eda76f91d
parent517acfdd56af4562d3c4f2963f656f2834ca23e2 (diff)
downloadscala-f5faa91d3d6ed21a2849f090c40082f95e7dc121.tar.gz
scala-f5faa91d3d6ed21a2849f090c40082f95e7dc121.tar.bz2
scala-f5faa91d3d6ed21a2849f090c40082f95e7dc121.zip
Merged revisions 24795-24796,24798-24800 via sv...
Merged revisions 24795-24796,24798-24800 via svnmerge from https://lampsvn.epfl.ch/svn-repos/scala/scala/trunk ........ r24795 | kzys | 2011-04-20 16:37:39 +0200 (Wed, 20 Apr 2011) | 2 lines [scaladoc] kindFilter should switch show/hide anchor of package. Closes #4463. Review by malayeri. ........ r24796 | extempore | 2011-04-20 18:28:01 +0200 (Wed, 20 Apr 2011) | 1 line Some tweaks to slice to make it run faster, no review. ........ r24798 | extempore | 2011-04-20 22:43:37 +0200 (Wed, 20 Apr 2011) | 6 lines One of the blips in the performance charts seems to implicate some changes I made with slice to reduce the number of implementations and surface area for inconsistencies and bugs. Altering those changes in a more performance-mindful way, although I don't see anything here which is likely to help much. Also fixing some wrong documentation about copyToArray. No review. ........ r24799 | extempore | 2011-04-21 07:00:54 +0200 (Thu, 21 Apr 2011) | 6 lines There is still all kinds of code in the pattern matcher which I've been dragging forward (for years now) unclear on the need for it but having been burned too many times by its undocumented ways. Returned to the fray once again and encountered shocking success levels with the abatement stick. Dumped all kinds of unnecessary code (or so we can hope) and seem close to fixing some fundamental issues. But we've heard that before. No review. ........ r24800 | odersky | 2011-04-21 11:31:18 +0200 (Thu, 21 Apr 2011) | 1 line Made FreshRunReq a traceable exception, so that we can better spot problems in the IDE. ........
-rw-r--r--src/compiler/scala/tools/nsc/doc/html/resource/lib/index.js7
-rw-r--r--src/compiler/scala/tools/nsc/interactive/CompilerControl.scala4
-rw-r--r--src/compiler/scala/tools/nsc/interactive/Global.scala7
-rw-r--r--src/compiler/scala/tools/nsc/interactive/Picklers.scala9
-rw-r--r--src/compiler/scala/tools/nsc/interactive/PresentationCompilerThread.scala4
-rw-r--r--src/compiler/scala/tools/nsc/matching/Matrix.scala16
-rw-r--r--src/compiler/scala/tools/nsc/matching/MatrixAdditions.scala105
-rw-r--r--src/compiler/scala/tools/nsc/matching/ParallelMatching.scala174
-rw-r--r--src/compiler/scala/tools/nsc/matching/Patterns.scala20
-rw-r--r--src/library/scala/collection/GenTraversableOnce.scala2
-rwxr-xr-xsrc/library/scala/collection/IndexedSeqOptimized.scala13
-rw-r--r--src/library/scala/collection/IterableLike.scala46
-rw-r--r--src/library/scala/collection/IterableViewLike.scala12
-rw-r--r--src/library/scala/collection/Iterator.scala7
-rwxr-xr-xsrc/library/scala/collection/LinearSeqOptimized.scala4
-rw-r--r--src/library/scala/collection/SeqViewLike.scala4
-rw-r--r--src/library/scala/collection/TraversableLike.scala8
-rw-r--r--src/library/scala/collection/immutable/List.scala6
-rw-r--r--src/library/scala/collection/mutable/ArrayOps.scala3
-rw-r--r--test/scaladoc/javascript/package.html1
-rw-r--r--test/scaladoc/javascript/test-index.html35
-rw-r--r--test/scaladoc/javascript/test-index.js17
22 files changed, 281 insertions, 223 deletions
diff --git a/src/compiler/scala/tools/nsc/doc/html/resource/lib/index.js b/src/compiler/scala/tools/nsc/doc/html/resource/lib/index.js
index 0f25f024f4..925f07bcb1 100644
--- a/src/compiler/scala/tools/nsc/doc/html/resource/lib/index.js
+++ b/src/compiler/scala/tools/nsc/doc/html/resource/lib/index.js
@@ -438,10 +438,13 @@ function kindFilter(kind) {
/* Applies the kind filter. */
function kindFilterSync() {
- if (kindFilterState == "all" || focusFilterState != null)
+ if (kindFilterState == "all" || focusFilterState != null) {
+ $("#tpl a.packhide").text('hide');
$("#tpl ol.templates").show();
- else
+ } else {
+ $("#tpl a.packhide").text('show');
$("#tpl ol.templates").hide();
+ }
}
function resizeFilterBlock() {
diff --git a/src/compiler/scala/tools/nsc/interactive/CompilerControl.scala b/src/compiler/scala/tools/nsc/interactive/CompilerControl.scala
index 64178b5eac..0c5d85d2a8 100644
--- a/src/compiler/scala/tools/nsc/interactive/CompilerControl.scala
+++ b/src/compiler/scala/tools/nsc/interactive/CompilerControl.scala
@@ -199,7 +199,7 @@ trait CompilerControl { self: Global =>
/** Cancels current compiler run and start a fresh one where everything will be re-typechecked
* (but not re-loaded).
*/
- def askReset() = scheduler raise FreshRunReq
+ def askReset() = scheduler raise (new FreshRunReq)
/** Tells the compile server to shutdown, and not to restart again */
def askShutdown() = scheduler raise ShutdownReq
@@ -307,7 +307,7 @@ trait CompilerControl { self: Global =>
/** Signals a request for a fresh background compiler run.
* Note: The object has to stay top-level so that the PresentationCompilerThread may access it.
*/
-object FreshRunReq extends ControlThrowable
+class FreshRunReq extends ControlThrowable
/** Signals a request for a shutdown of the presentation compiler.
* Note: The object has to stay top-level so that the PresentationCompilerThread may access it.
diff --git a/src/compiler/scala/tools/nsc/interactive/Global.scala b/src/compiler/scala/tools/nsc/interactive/Global.scala
index 9b50b82bb3..2b920c8c03 100644
--- a/src/compiler/scala/tools/nsc/interactive/Global.scala
+++ b/src/compiler/scala/tools/nsc/interactive/Global.scala
@@ -173,7 +173,7 @@ class Global(settings: Settings, reporter: Reporter, projectName: String = "")
def isOutOfDate: Boolean = outOfDate
def demandNewCompilerRun() = {
- if (outOfDate) throw FreshRunReq // cancel background compile
+ if (outOfDate) throw new FreshRunReq // cancel background compile
else outOfDate = true // proceed normally and enable new background compile
}
@@ -316,7 +316,7 @@ class Global(settings: Settings, reporter: Reporter, projectName: String = "")
}
logreplay("exception thrown", scheduler.pollThrowable()) match {
- case Some(ex @ FreshRunReq) =>
+ case Some(ex: FreshRunReq) =>
newTyperRun()
minRunId = currentRunId
demandNewCompilerRun()
@@ -537,9 +537,10 @@ class Global(settings: Settings, reporter: Reporter, projectName: String = "")
} catch {
case CancelException =>
debugLog("cancelled")
- case ex @ FreshRunReq =>
+ case ex: FreshRunReq =>
if (debugIDE) {
println("FreshRunReq thrown during response")
+ ex.printStackTrace()
}
response raise ex
throw ex
diff --git a/src/compiler/scala/tools/nsc/interactive/Picklers.scala b/src/compiler/scala/tools/nsc/interactive/Picklers.scala
index 53ef20507f..561fa47e94 100644
--- a/src/compiler/scala/tools/nsc/interactive/Picklers.scala
+++ b/src/compiler/scala/tools/nsc/interactive/Picklers.scala
@@ -16,8 +16,13 @@ import mutable.ListBuffer
trait Picklers { self: Global =>
- lazy val freshRunReq = singletonPickler(FreshRunReq)
- lazy val shutdownReq = singletonPickler(ShutdownReq)
+ lazy val freshRunReq =
+ unitPickler
+ .wrapped { _ => new FreshRunReq } { x => () }
+ .labelled ("FreshRunReq")
+ .cond (_.isInstanceOf[FreshRunReq])
+
+ lazy val shutdownReq = singletonPickler(ShutdownReq)
def defaultThrowable[T <: Throwable]: CondPickler[T] = javaInstancePickler[T] cond { _ => true }
diff --git a/src/compiler/scala/tools/nsc/interactive/PresentationCompilerThread.scala b/src/compiler/scala/tools/nsc/interactive/PresentationCompilerThread.scala
index 4ba0208c39..098884dab1 100644
--- a/src/compiler/scala/tools/nsc/interactive/PresentationCompilerThread.scala
+++ b/src/compiler/scala/tools/nsc/interactive/PresentationCompilerThread.scala
@@ -24,7 +24,7 @@ final class PresentationCompilerThread(var compiler: Global, name: String = "")
try {
compiler.backgroundCompile()
} catch {
- case FreshRunReq =>
+ case ex: FreshRunReq =>
compiler.debugLog("fresh run req caught, starting new pass")
}
compiler.log.flush()
@@ -40,7 +40,7 @@ final class PresentationCompilerThread(var compiler: Global, name: String = "")
compiler.log.flush()
ex match {
- case FreshRunReq =>
+ case ex: FreshRunReq =>
compiler.debugLog("fresh run req caught outside presentation compiler loop; ignored") // This shouldn't be reported
case _ : Global#ValidateException => // This will have been reported elsewhere
compiler.debugLog("validate exception caught outside presentation compiler loop; ignored")
diff --git a/src/compiler/scala/tools/nsc/matching/Matrix.scala b/src/compiler/scala/tools/nsc/matching/Matrix.scala
index 2532801d83..5648f97f84 100644
--- a/src/compiler/scala/tools/nsc/matching/Matrix.scala
+++ b/src/compiler/scala/tools/nsc/matching/Matrix.scala
@@ -88,21 +88,17 @@ trait Matrix extends MatrixAdditions {
context: MatrixContext): Tree =
{
import context._
- // log("handlePattern: selector.tpe = " + selector.tpe)
- // sets up top level match
val matrixInit: MatrixInit = {
val v = copyVar(selector, isChecked, selector.tpe, "temp")
MatrixInit(List(v), cases, atPos(selector.pos)(MATCHERROR(v.ident)))
}
-
- val matrix = new MatchMatrix(context) { lazy val data = matrixInit }
- val rep = matrix.expansion // expands casedefs and assigns name
- val mch = typer typed rep.toTree // executes algorithm, converts tree to DFA
- val dfatree = typer typed Block(matrixInit.valDefs, mch) // packages into a code block
+ val matrix = new MatchMatrix(context) { lazy val data = matrixInit }
+ val mch = typer typed matrix.expansion.toTree
+ val dfatree = typer typed Block(matrix.data.valDefs, mch)
// redundancy check
- matrix.targets filter (_.isNotReached) foreach (cs => cunit.error(cs.body.pos, "unreachable code"))
+ matrix.targets filter (_.unreached) foreach (cs => cunit.error(cs.body.pos, "unreachable code"))
// optimize performs squeezing and resets any remaining NO_EXHAUSTIVE
tracing("handlePattern")(matrix optimize dfatree)
}
@@ -168,9 +164,9 @@ trait Matrix extends MatrixAdditions {
val emptyPatternVarGroup = PatternVarGroup()
class PatternVarGroup(val pvs: List[PatternVar]) {
- def syms = pvs map (_.sym)
+ def syms = pvs map (_.sym)
def valDefs = pvs map (_.valDef)
- def idents = pvs map (_.ident)
+ def idents = pvs map (_.ident)
def extractIndex(index: Int): (PatternVar, PatternVarGroup) = {
val (t, ts) = self.extractIndex(pvs, index)
diff --git a/src/compiler/scala/tools/nsc/matching/MatrixAdditions.scala b/src/compiler/scala/tools/nsc/matching/MatrixAdditions.scala
index 3b481dd03e..e59d8c7858 100644
--- a/src/compiler/scala/tools/nsc/matching/MatrixAdditions.scala
+++ b/src/compiler/scala/tools/nsc/matching/MatrixAdditions.scala
@@ -12,8 +12,7 @@ import PartialFunction._
/** Traits which are mixed into MatchMatrix, but separated out as
* (somewhat) independent components to keep them on the sidelines.
*/
-trait MatrixAdditions extends ast.TreeDSL
-{
+trait MatrixAdditions extends ast.TreeDSL {
self: ExplicitOuter with ParallelMatching =>
import global.{ typer => _, _ }
@@ -30,50 +29,52 @@ trait MatrixAdditions extends ast.TreeDSL
private val settings_squeeze = !settings.Ynosqueeze.value
- def squeezedBlockPVs(pvs: List[PatternVar], exp: Tree): Tree =
- squeezedBlock(pvs map (_.valDef), exp)
+ class RefTraverser(vd: ValDef) extends Traverser {
+ private val targetSymbol = vd.symbol
+ private var safeRefs = 0
+ private var isSafe = true
- /** Compresses multiple Blocks. */
- def mkBlock(stats: List[Tree], expr: Tree): Tree = expr match {
- case Block(stats1, expr1) if stats.isEmpty => mkBlock(stats1, expr1)
- case _ => Block(stats, expr)
- }
+ def canDrop = isSafe && safeRefs == 0
+ def canInline = isSafe && safeRefs == 1
- def squeezedBlock(vds: List[Tree], exp: Tree): Tree =
- if (settings_squeeze) mkBlock(Nil, squeezedBlock1(vds, exp))
- else mkBlock(vds, exp)
+ override def traverse(tree: Tree): Unit = tree match {
+ case t: Ident if t.symbol eq targetSymbol =>
+ // target symbol's owner should match currentOwner
+ if (targetSymbol.owner == currentOwner) safeRefs += 1
+ else isSafe = false
- private def squeezedBlock1(vds: List[Tree], exp: Tree): Tree = {
- class RefTraverser(sym: Symbol) extends Traverser {
- var nref, nsafeRef = 0
- override def traverse(tree: Tree) = tree match {
- case t: Ident if t.symbol eq sym =>
- nref += 1
- if (sym.owner == currentOwner) // oldOwner should match currentOwner
- nsafeRef += 1
-
- case LabelDef(_, args, rhs) =>
- (args dropWhile(_.symbol ne sym)) match {
- case Nil =>
- case _ => nref += 2 // cannot substitute this one
- }
- traverse(rhs)
- case t if nref > 1 => // abort, no story to tell
- case t =>
- super.traverse(t)
- }
- }
+ case LabelDef(_, params, rhs) =>
+ if (params exists (_.symbol eq targetSymbol)) // cannot substitute this one
+ isSafe = false
- class Subst(sym: Symbol, rhs: Tree) extends Transformer {
- var stop = false
- override def transform(tree: Tree) = tree match {
- case t: Ident if t.symbol == sym =>
- stop = true
- rhs
- case _ => if (stop) tree else super.transform(tree)
- }
+ traverse(rhs)
+ case _ if safeRefs > 1 => ()
+ case _ =>
+ super.traverse(tree)
+ }
+ }
+ class Subst(vd: ValDef) extends Transformer {
+ private var stop = false
+ override def transform(tree: Tree): Tree = tree match {
+ case t: Ident if t.symbol == vd.symbol =>
+ stop = true
+ vd.rhs
+ case _ =>
+ if (stop) tree
+ else super.transform(tree)
}
+ }
+
+ /** Compresses multiple Blocks. */
+ private def combineBlocks(stats: List[Tree], expr: Tree): Tree = expr match {
+ case Block(stats1, expr1) if stats.isEmpty => combineBlocks(stats1, expr1)
+ case _ => Block(stats, expr)
+ }
+ def squeezedBlock(vds: List[Tree], exp: Tree): Tree =
+ if (settings_squeeze) combineBlocks(Nil, squeezedBlock1(vds, exp))
+ else combineBlocks(vds, exp)
+ private def squeezedBlock1(vds: List[Tree], exp: Tree): Tree = {
lazy val squeezedTail = squeezedBlock(vds.tail, exp)
def default = squeezedTail match {
case Block(vds2, exp2) => Block(vds.head :: vds2, exp2)
@@ -83,17 +84,13 @@ trait MatrixAdditions extends ast.TreeDSL
if (vds.isEmpty) exp
else vds.head match {
case vd: ValDef =>
- val sym = vd.symbol
- val rt = new RefTraverser(sym)
- rt.atOwner (owner) (rt traverse squeezedTail)
-
- rt.nref match {
- case 0 => squeezedTail
- case 1 if rt.nsafeRef == 1 => new Subst(sym, vd.rhs) transform squeezedTail
- case _ => default
- }
- case _ =>
- default
+ val rt = new RefTraverser(vd)
+ rt.atOwner(owner)(rt traverse squeezedTail)
+
+ if (rt.canDrop) squeezedTail
+ else if (rt.canInline) new Subst(vd) transform squeezedTail
+ else default
+ case _ => default
}
}
}
@@ -109,9 +106,7 @@ trait MatrixAdditions extends ast.TreeDSL
object lxtt extends Transformer {
override def transform(tree: Tree): Tree = tree match {
case blck @ Block(vdefs, ld @ LabelDef(name, params, body)) =>
- def shouldInline(t: FinalState) = t.isReachedOnce && (t.labelSym eq ld.symbol)
-
- if (targets exists shouldInline) squeezedBlock(vdefs, body)
+ if (targets exists (_ shouldInline ld.symbol)) squeezedBlock(vdefs, body)
else blck
case t =>
@@ -166,7 +161,7 @@ trait MatrixAdditions extends ast.TreeDSL
private def requiresExhaustive(sym: Symbol) = {
(sym.isMutable) && // indicates that have not yet checked exhaustivity
- !(sym hasFlag NO_EXHAUSTIVE) && // indicates @unchecked
+ !(sym hasFlag NO_EXHAUSTIVE) && // indicates @unchecked
(sym.tpe.typeSymbol.isSealed) &&
!isValueClass(sym.tpe.typeSymbol) // make sure it's not a primitive, else (5: Byte) match { case 5 => ... } sees no Byte
}
diff --git a/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala b/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala
index 89e849d038..1b0265ce5d 100644
--- a/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala
+++ b/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala
@@ -25,7 +25,7 @@ trait ParallelMatching extends ast.TreeDSL
self: ExplicitOuter =>
import global.{ typer => _, _ }
- import definitions.{ AnyRefClass, IntClass, BooleanClass, getProductArgs, productProj }
+ import definitions.{ AnyRefClass, NothingClass, IntClass, BooleanClass, getProductArgs, productProj }
import CODE._
import Types._
import Debug._
@@ -55,16 +55,8 @@ trait ParallelMatching extends ast.TreeDSL
*/
final def requestBody(bx: Int, subst: Bindings): Tree = {
// shortcut
- if (bx < 0)
- return Apply(ID(shortCuts(-bx-1)), Nil)
-
- val pvgroup = PatternVarGroup.fromBindings(subst.get(), targets(bx).freeVars)
- val target = targets(bx)
-
- // first time this bx is requested - might be bound elsewhere
- if (target.isNotReached) target.createLabelBody(bx, pvgroup)
- // call label "method" if possible
- else target.getLabelBody(pvgroup)
+ if (bx < 0) Apply(ID(shortCuts(-bx-1)), Nil)
+ else targets(bx) labelBody subst
}
/** the injection here handles alternatives and unapply type tests */
@@ -107,9 +99,9 @@ trait ParallelMatching extends ast.TreeDSL
def allValDefs = extraValDefs ::: accessorPatternVars.valDefs
// tests
- def isDefined = sym ne NoSymbol
- def isSimple = tpe.isByte || tpe.isShort || tpe.isChar || tpe.isInt
- def isCaseClass = tpe.typeSymbol.isCase
+ def isDefined = sym ne NoSymbol
+ def isSubrangeType = Set(ByteClass, ShortClass, CharClass, IntClass) contains tpe.typeSymbol
+ def isCaseClass = tpe.typeSymbol.isCase
// sequences
def seqType = tpe.widen baseType SeqClass
@@ -144,7 +136,7 @@ trait ParallelMatching extends ast.TreeDSL
// ... should compile to a switch. It doesn't because the scrut isn't Int/Char, but
// that could be handle in an if/else since every pattern requires an Int.
// More immediately, Byte and Short scruts should also work.
- if (!scrut.isSimple) None
+ if (!scrut.isSubrangeType) None
else {
val (_lits, others) = ps span isSwitchableConst
val lits = _lits collect { case x: LiteralPattern => x }
@@ -162,7 +154,7 @@ trait ParallelMatching extends ast.TreeDSL
override val ps: List[LiteralPattern],
val defaultPattern: Option[Pattern]
) extends PatternMatch(scrut, ps) {
- require(scrut.isSimple && (ps forall (_.isSwitchable)))
+ require(scrut.isSubrangeType && (ps forall (_.isSwitchable)))
}
case class PatternMatch(scrut: Scrutinee, ps: List[Pattern]) {
@@ -217,17 +209,6 @@ trait ParallelMatching extends ast.TreeDSL
def MixtureRule(scrut: Scrutinee, column: List[Pattern], rest: Rep): RuleApplication =
PatternMatch(scrut, column) mkRule rest
- /**
- * Class encapsulating a guard expression in a pattern match:
- * case ... if(tree) => ...
- */
- case class Guard(tree: Tree) {
- def isEmpty = tree.isEmpty
- def duplicate = Guard(tree.duplicate)
- override def toString() = if (isEmpty) "" else " // if %s" format tree
- }
- val NoGuard = Guard(EmptyTree)
-
/***** Rule Applications *****/
sealed abstract class RuleApplication {
@@ -263,14 +244,13 @@ trait ParallelMatching extends ast.TreeDSL
/** {case ... if guard => bx} else {guardedRest} */
/** VariableRule: The top-most rows has only variable (non-constructor) patterns. */
- case class VariableRule(subst: Bindings, guard: Guard, guardedRest: Rep, bx: Int) extends RuleApplication {
+ case class VariableRule(subst: Bindings, guard: Tree, guardedRest: Rep, bx: Int) extends RuleApplication {
def pmatch: PatternMatch = impossible
def rest: Rep = guardedRest
- lazy val cond = if (guard.isEmpty) TRUE else guard.duplicate.tree
+ lazy val cond = if (guard.isEmpty) TRUE else guard
lazy val success = requestBody(bx, subst)
lazy val failure = guardedRest.toTree
-
lazy val pvgroup = PatternVarGroup.fromBindings(subst.get())
final def tree(): Tree =
@@ -278,11 +258,7 @@ trait ParallelMatching extends ast.TreeDSL
else squeezedBlock(pvgroup.valDefs, codegen)
}
- /** Mixture rule for all literal ints (and chars) i.e. hopefully a switch
- * will be emitted on the JVM.
- */
- class MixLiteralInts(val pmatch: PatternSwitch, val rest: Rep) extends RuleApplication
- {
+ class MixLiteralInts(val pmatch: PatternSwitch, val rest: Rep) extends RuleApplication {
val literals = pmatch.ps
val defaultPattern = pmatch.defaultPattern
@@ -312,42 +288,41 @@ trait ParallelMatching extends ast.TreeDSL
case None => (Nil, Nil)
case Some(Pattern(_, vs)) => (vs, List(rebindAll(rest rows literals.size, vs, scrut.sym)))
}
+
// literalMap is a map from each literal to a list of row indices.
// varMap is a list from each literal to a list of the defined vars.
- lazy val (literalMap, varMap) = {
- val tags = literals map (_.intValue)
- val varMap = tags zip (literals map (_.deepBoundVariables))
- val litMap =
- tags.zipWithIndex.reverse.foldLeft(IntMap.empty[List[Int]]) {
- // we reverse before the fold so the list can be built with ::
- case (map, (tag, index)) => map.updated(tag, index :: map.getOrElse(tag, Nil))
- }
-
- (litMap, varMap)
+ lazy val (litPairs, varMap) = (
+ literals.zipWithIndex map {
+ case (lit, index) =>
+ val tag = lit.intValue
+ (tag -> index, tag -> lit.deepBoundVariables)
+ } unzip
+ )
+ def literalMap = litPairs groupBy (_._1) map {
+ case (k, vs) => (k, vs map (_._2))
}
lazy val cases =
for ((tag, indices) <- literalMap.toList) yield {
val newRows = indices map (i => addDefaultVars(i)(rest rows i))
- val r = remake(newRows ::: defaultRows, includeScrut = false)
- val r2 = make(r.tvars, r.rows map (x => x rebind bindVars(tag, x.subst)))
+ val r = remake(newRows ++ defaultRows, includeScrut = false)
+ val r2 = make(r.tvars, r.rows map (x => x rebind bindVars(tag, x.subst)))
CASE(Literal(tag)) ==> r2.toTree
}
- lazy val defaultTree = remake(defaultRows, includeScrut = false).toTree
- def casesWithDefault = cases ::: List(CASE(WILD(IntClass.tpe)) ==> defaultTree)
+ lazy val defaultTree = remake(defaultRows, includeScrut = false).toTree
+ def defaultCase = CASE(WILD(IntClass.tpe)) ==> defaultTree
// cond/success/failure only used if there is exactly one case.
- lazy val (cond, success) = cases match {
- case List(CaseDef(lit, _, body)) => (scrut.id MEMBER_== lit, body)
- }
+ lazy val cond = scrut.id MEMBER_== cases.head.pat
+ lazy val success = cases.head.body
lazy val failure = defaultTree
// only one case becomes if/else, otherwise match
def tree() =
if (cases.size == 1) codegen
- else casted MATCH (casesWithDefault: _*)
+ else casted MATCH (cases :+ defaultCase: _*)
}
/** mixture rule for unapply pattern
@@ -426,7 +401,7 @@ trait ParallelMatching extends ast.TreeDSL
val (squeezePVs, pvs, rows) = doSuccess
val srep = remake(rows, pvs).toTree
- squeezedBlockPVs(squeezePVs, srep)
+ squeezedBlock(squeezePVs map (_.valDef), srep)
}
final def tree() =
@@ -521,7 +496,7 @@ trait ParallelMatching extends ast.TreeDSL
// wrapping in a null check on the scrutinee
nullSafe(compareFn, FALSE)(scrut.id)
}
- lazy val success = squeezedBlockPVs(pvs, remake(successRows, pvs, hasStar).toTree)
+ lazy val success = squeezedBlock(pvs map (_.valDef), remake(successRows, pvs, hasStar).toTree)
lazy val failure = remake(failRows).toTree
final def tree(): Tree = codegen
@@ -535,7 +510,7 @@ trait ParallelMatching extends ast.TreeDSL
private lazy val rhs =
decodedEqualsType(head.tpe) match {
case SingleType(pre, sym) => REF(pre, sym)
- case PseudoType(o) => o.duplicate
+ case PseudoType(o) => o
}
lazy val label =
@@ -546,7 +521,7 @@ trait ParallelMatching extends ast.TreeDSL
lazy val success = remake(List(
rest.rows.head.insert2(List(NoPattern), head.boundVariables, scrut.sym),
- Row(emptyPatterns(1 + rest.tvars.size), NoBinding, NoGuard, shortCut(label))
+ Row(emptyPatterns(1 + rest.tvars.size), NoBinding, EmptyTree, shortCut(label))
)).toTree
lazy val failure = LabelDef(label, Nil, labelBody)
@@ -637,7 +612,7 @@ trait ParallelMatching extends ast.TreeDSL
/*** States, Rows, Etc. ***/
- case class Row(pats: List[Pattern], subst: Bindings, guard: Guard, bx: Int) {
+ case class Row(pats: List[Pattern], subst: Bindings, guard: Tree, bx: Int) {
private def nobindings = subst.get().isEmpty
private def bindstr = if (nobindings) "" else pp(subst)
// if (pats exists (p => !p.isDefault))
@@ -693,8 +668,8 @@ trait ParallelMatching extends ast.TreeDSL
def vprint(vs: List[Any]) = if (vs.isEmpty) "" else ": %s".format(pp(vs))
def rprint(r: Row) = pp(r)
def tprint(t: FinalState) =
- if (t.freeVars.isEmpty) " ==> %s".format(pp(t.body))
- else " ==>\n %s".format(pp(t.freeVars -> t.body))
+ if (t.params.isEmpty) " ==> %s".format(pp(t.body))
+ else " ==>\n %s".format(pp(t.params -> t.body))
val xs = rows zip targets map { case (r,t) => rprint(r) + tprint(t) }
val ppstr = pp(xs, newlines = true)
@@ -703,70 +678,38 @@ trait ParallelMatching extends ast.TreeDSL
}
}
- abstract class State {
- def body: Tree
- def freeVars: List[Symbol]
- def isFinal: Boolean
- }
-
- case class FinalState(bx: Int, body: Tree, freeVars: List[Symbol]) extends State {
+ case class FinalState(bx: Int, body: Tree, params: List[Symbol]) {
private var referenceCount = 0
- private var _label: LabelDef = null
- private var _labelSym: Symbol = null
-
- def labelSym = _labelSym
- def label = _label
-
- // @bug: typer is not able to digest a body of type Nothing being assigned result type Unit
- def bodyTpe = if (body.tpe.isNothing) body.tpe else matchResultType
- def duplicate = body.duplicate setType bodyTpe
-
- def isFinal = true
- def isLabellable = !cond(body) { case _: Literal => true }
- def isNotReached = referenceCount == 0
- def isReachedOnce = referenceCount == 1
- def isReachedTwice = referenceCount > 1
-
- // arguments to pass to this body%xx
- def labelParamTypes = label.tpe.paramTypes
-
- def createLabelBody(index: Int, pvgroup: PatternVarGroup) = {
- val args = pvgroup.syms
- val vdefs = pvgroup.valDefs
-
- val name = "body%" + index
- require(_labelSym == null)
- referenceCount += 1
-
- if (isLabellable) {
- val mtype = MethodType(freeVars, bodyTpe)
- _labelSym = owner.newLabel(body.pos, name) setInfo mtype
- _label = typer typedLabelDef LabelDef(_labelSym, freeVars, body setType bodyTpe)
- // TRACE("Creating index %d: mtype = %s".format(bx, mtype))
- // TRACE("[New label] def %s%s: %s = %s".format(name, pp(freeVars), bodyTpe, body))
- }
-
- ifLabellable(vdefs, squeezedBlock(vdefs, label))
+ // typer is not able to digest a body of type Nothing being assigned result type Unit
+ private def caseResultType = if (body.tpe.isNothing) body.tpe else matchResultType
+ private lazy val label: LabelDef = body match {
+ case Literal(_) => null
+ case _ =>
+ val symbol = owner.newLabel(body.pos, "body%" + bx) setInfo MethodType(params, caseResultType)
+ // typer typedLabelDef
+ LabelDef(symbol, params, body setType caseResultType)
}
- def getLabelBody(pvgroup: PatternVarGroup): Tree = {
- val idents = pvgroup map (_.rhs)
- val vdefs = pvgroup.valDefs
+ def unreached = referenceCount == 0
+ def shouldInline(sym: Symbol) = referenceCount == 1 && label != null && label.symbol == sym
+
+ def labelBody(subst: Bindings): Tree = {
referenceCount += 1
+ val pvgroup = PatternVarGroup.fromBindings(subst.get(), params)
- ifLabellable(vdefs, ID(labelSym) APPLY (idents))
+ if (referenceCount > 1 && label != null)
+ ID(label.symbol) APPLY (pvgroup map (_.rhs))
+ else squeezedBlock(pvgroup.valDefs,
+ if (label != null) label
+ else body.duplicate setType caseResultType
+ )
}
-
- private def ifLabellable(vdefs: List[Tree], t: => Tree) =
- if (isLabellable) t
- else squeezedBlock(vdefs, duplicate)
-
- override def toString() = pp("Final%d%s".format(bx, pp(freeVars)) -> body)
+ override def toString() = pp("Final%d%s".format(bx, pp(params)) -> body)
}
case class Rep(val tvars: PatternVarGroup, val rows: List[Row]) {
lazy val Row(pats, subst, guard, index) = rows.head
- lazy val guardedRest = if (guard.isEmpty) NoRep else make(tvars, rows.tail)
+ lazy val guardedRest = if (guard.isEmpty) Rep(Nil, Nil) else make(tvars, rows.tail)
lazy val (defaults, others) = pats span (_.isDefault)
/** Sealed classes. */
@@ -818,12 +761,11 @@ trait ParallelMatching extends ast.TreeDSL
else "Rep(%dx%d)%s%s".format(tvars.size, rows.size, ppn(tvars), ppn(rows))
}
- val NoRep = Rep(Nil, Nil)
/** Expands the patterns recursively. */
final def expand(roots: List[PatternVar], cases: List[CaseDef]) =
tracing("Expanded")(ExpandedMatrix(
for ((CaseDef(pat, guard, body), index) <- cases.zipWithIndex) yield {
- def mkRow(ps: List[Tree]) = Row(toPats(ps), NoBinding, Guard(guard), index)
+ def mkRow(ps: List[Tree]) = Row(toPats(ps), NoBinding, guard, index)
val pattern = Pattern(pat)
val row = mkRow(pat match {
diff --git a/src/compiler/scala/tools/nsc/matching/Patterns.scala b/src/compiler/scala/tools/nsc/matching/Patterns.scala
index 40ff73e648..742ab32736 100644
--- a/src/compiler/scala/tools/nsc/matching/Patterns.scala
+++ b/src/compiler/scala/tools/nsc/matching/Patterns.scala
@@ -98,7 +98,15 @@ trait Patterns extends ast.TreeDSL {
require (args.isEmpty)
val Apply(select: Select, _) = tree
- override def sufficientType = mkSingletonFromQualifier
+ override lazy val sufficientType = qualifier.tpe match {
+ case t: ThisType => singleType(t, sym) // this.X
+ case _ =>
+ qualifier match {
+ case _: Apply => PseudoType(tree)
+ case _ => singleType(Pattern(qualifier).necessaryType, sym)
+ }
+ }
+
override def simplify(pv: PatternVar) = this.rebindToObjectCheck()
override def description = backticked match {
case Some(s) => "this." + s
@@ -382,16 +390,6 @@ trait Patterns extends ast.TreeDSL {
case Apply(f, Nil) => getPathSegments(f)
case _ => Nil
}
- protected def mkSingletonFromQualifier = {
- def pType = qualifier match {
- case _: Apply => PseudoType(tree)
- case _ => singleType(Pattern(qualifier).necessaryType, sym)
- }
- qualifier.tpe match {
- case t: ThisType => singleType(t, sym) // this.X
- case _ => pType
- }
- }
}
sealed trait NamePattern extends Pattern {
diff --git a/src/library/scala/collection/GenTraversableOnce.scala b/src/library/scala/collection/GenTraversableOnce.scala
index 053a6d211a..fb18ce1d72 100644
--- a/src/library/scala/collection/GenTraversableOnce.scala
+++ b/src/library/scala/collection/GenTraversableOnce.scala
@@ -367,7 +367,7 @@ private[collection] trait GenTraversableOnce[+A] {
def copyToArray[B >: A](xs: Array[B]): Unit
/** Copies values of this $coll to an array.
- * Fills the given array `xs` with values of this $coll, after skipping `start` values.
+ * Fills the given array `xs` with values of this $coll, beginning at index `start`.
* Copying will stop once either the end of the current $coll is reached,
* or the end of the array is reached.
*
diff --git a/src/library/scala/collection/IndexedSeqOptimized.scala b/src/library/scala/collection/IndexedSeqOptimized.scala
index 04d89299c8..b9a60ae1f1 100755
--- a/src/library/scala/collection/IndexedSeqOptimized.scala
+++ b/src/library/scala/collection/IndexedSeqOptimized.scala
@@ -103,11 +103,11 @@ trait IndexedSeqOptimized[+A, +Repr] extends IndexedSeqLike[A, Repr] { self =>
override /*IterableLike*/
def slice(from: Int, until: Int): Repr = {
- val lo = from max 0
- val hi = until min length
- val elems = hi - lo
+ val lo = math.max(from, 0)
+ val hi = math.min(until, length)
+ val elems = math.max(hi - lo, 0)
val b = newBuilder
- b.sizeHint(elems max 0)
+ b.sizeHint(elems)
var i = lo
while (i < hi) {
@@ -185,11 +185,10 @@ trait IndexedSeqOptimized[+A, +Repr] extends IndexedSeqLike[A, Repr] { self =>
override /*SeqLike*/
def segmentLength(p: A => Boolean, from: Int): Int = {
- val start = from
val len = length
- var i = start
+ var i = from
while (i < len && p(this(i))) i += 1
- i - start
+ i - from
}
private def negLength(n: Int) = if (n >= length) -1 else n
diff --git a/src/library/scala/collection/IterableLike.scala b/src/library/scala/collection/IterableLike.scala
index 458b26207e..b6713b65e4 100644
--- a/src/library/scala/collection/IterableLike.scala
+++ b/src/library/scala/collection/IterableLike.scala
@@ -90,9 +90,49 @@ self =>
iterator.next
override /*TraversableLike*/ def slice(from: Int, until: Int): Repr = {
- val lo = from max 0
- if (until <= lo) newBuilder.result
- else newBuilder ++= (iterator drop lo take (until - lo)) result
+ val lo = math.max(from, 0)
+ val elems = until - lo
+ val b = newBuilder
+ if (elems <= 0) b.result
+ else {
+ b.sizeHintBounded(elems, this)
+ var i = 0
+ val it = iterator drop lo
+ while (i < elems && it.hasNext) {
+ b += it.next
+ i += 1
+ }
+ b.result
+ }
+ }
+
+ override /*TraversableLike*/ def take(n: Int): Repr = {
+ val b = newBuilder
+
+ if (n <= 0) b.result
+ else {
+ b.sizeHintBounded(n, this)
+ var i = 0
+ val it = iterator
+ while (i < n && it.hasNext) {
+ b += it.next
+ i += 1
+ }
+ b.result
+ }
+ }
+
+ override /*TraversableLike*/ def drop(n: Int): Repr = {
+ val b = newBuilder
+ val lo = math.max(0, n)
+ b.sizeHint(this, -lo)
+ var i = 0
+ val it = iterator
+ while (i < n && it.hasNext) {
+ it.next
+ i += 1
+ }
+ b ++= it result
}
override /*TraversableLike*/ def takeWhile(p: A => Boolean): Repr = {
diff --git a/src/library/scala/collection/IterableViewLike.scala b/src/library/scala/collection/IterableViewLike.scala
index e0e1329844..e0f1ada2b8 100644
--- a/src/library/scala/collection/IterableViewLike.scala
+++ b/src/library/scala/collection/IterableViewLike.scala
@@ -63,6 +63,8 @@ trait IterableViewLike[+A,
trait ZippedAll[A1 >: A, B] extends Transformed[(A1, B)] with super[GenIterableViewLike].ZippedAll[A1, B]
+ private[this] implicit def asThis(xs: Transformed[A]): This = xs.asInstanceOf[This]
+
/** Boilerplate method, to override in each subclass
* This method could be eliminated if Scala had virtual classes
*/
@@ -81,6 +83,16 @@ trait IterableViewLike[+A,
protected override def newDroppedWhile(p: A => Boolean): Transformed[A] = new { val pred = p } with DroppedWhile
protected override def newTakenWhile(p: A => Boolean): Transformed[A] = new { val pred = p } with TakenWhile
+ // After adding take and drop overrides to IterableLike, these overrides (which do nothing
+ // but duplicate the implementation in TraversableViewLike) had to be added to prevent the
+ // overrides in IterableLike from besting the overrides in TraversableViewLike when mixed
+ // together in e.g. SeqViewLike. This is a suboptimal situation. Examples of failing tests
+ // are run/bug2876 and run/viewtest.
+ protected override def newTaken(n: Int): Transformed[A] = newSliced(SliceInterval(0, n))
+ protected override def newDropped(n: Int): Transformed[A] = newSliced(SliceInterval(n, Int.MaxValue))
+ override def drop(n: Int): This = newDropped(n)
+ override def take(n: Int): This = newTaken(n)
+
override def zip[A1 >: A, B, That](that: GenIterable[B])(implicit bf: CanBuildFrom[This, (A1, B), That]): That = {
newZipped(that).asInstanceOf[That]
// was: val b = bf(repr)
diff --git a/src/library/scala/collection/Iterator.scala b/src/library/scala/collection/Iterator.scala
index 7bd33cbb23..39c1d5b07f 100644
--- a/src/library/scala/collection/Iterator.scala
+++ b/src/library/scala/collection/Iterator.scala
@@ -975,8 +975,8 @@ trait Iterator[+A] extends TraversableOnce[A] {
}
/** Copies selected values produced by this iterator to an array.
- * Fills the given array `xs` with at most `len` values produced by this
- * iterator, after skipping `start` values.
+ * Fills the given array `xs` starting at index `start` with at most
+ * `len` values produced by this iterator.
* Copying will stop once either the end of the current iterator is reached,
* or the end of the array is reached, or `len` elements have been copied.
*
@@ -987,12 +987,11 @@ trait Iterator[+A] extends TraversableOnce[A] {
* @param len the maximal number of elements to copy.
* @tparam B the type of the elements of the array.
*
- *
* @usecase def copyToArray(xs: Array[A], start: Int, len: Int): Unit
*/
def copyToArray[B >: A](xs: Array[B], start: Int, len: Int): Unit = {
var i = start
- val end = start + len min xs.length
+ val end = start + math.min(len, xs.length)
while (hasNext && i < end) {
xs(i) = next()
i += 1
diff --git a/src/library/scala/collection/LinearSeqOptimized.scala b/src/library/scala/collection/LinearSeqOptimized.scala
index 7c5cba0665..236a5bdaa3 100755
--- a/src/library/scala/collection/LinearSeqOptimized.scala
+++ b/src/library/scala/collection/LinearSeqOptimized.scala
@@ -168,7 +168,9 @@ trait LinearSeqOptimized[+A, +Repr <: LinearSeqOptimized[A, Repr]] extends Linea
// since we are in collection.*, not immutable.*.
// However making that change will pessimize all the
// immutable linear seqs (like list) which surely expect
- // drop to share.
+ // drop to share. (Or at least it would penalize List if
+ // it didn't override drop. It would be a lot better if
+ // the leaf collections didn't override so many methods.)
//
// Upshot: MutableList is broken and passes part of the
// original list as the result of drop.
diff --git a/src/library/scala/collection/SeqViewLike.scala b/src/library/scala/collection/SeqViewLike.scala
index f79baa7c58..77dc15e695 100644
--- a/src/library/scala/collection/SeqViewLike.scala
+++ b/src/library/scala/collection/SeqViewLike.scala
@@ -93,6 +93,10 @@ trait SeqViewLike[+A,
} with Patched[B]
protected def newPrepended[B >: A](elem: B): Transformed[B] = new { protected[this] val fst = elem } with Prepended[B]
+ // see comment in IterableViewLike.
+ protected override def newTaken(n: Int): Transformed[A] = newSliced(SliceInterval(0, n))
+ protected override def newDropped(n: Int): Transformed[A] = newSliced(SliceInterval(n, Int.MaxValue))
+
override def reverse: This = newReversed.asInstanceOf[This]
override def patch[B >: A, That](from: Int, patch: GenSeq[B], replaced: Int)(implicit bf: CanBuildFrom[This, B, That]): That = {
diff --git a/src/library/scala/collection/TraversableLike.scala b/src/library/scala/collection/TraversableLike.scala
index 2d3a4c229c..fe1d5d7d77 100644
--- a/src/library/scala/collection/TraversableLike.scala
+++ b/src/library/scala/collection/TraversableLike.scala
@@ -434,10 +434,14 @@ trait TraversableLike[+A, +Repr] extends HasNewBuilder[A, Repr]
def take(n: Int): Repr = slice(0, n)
def drop(n: Int): Repr =
- if (n <= 0) newBuilder ++= thisCollection result
+ if (n <= 0) {
+ val b = newBuilder
+ b.sizeHint(this)
+ b ++= thisCollection result
+ }
else sliceWithKnownDelta(n, Int.MaxValue, -n)
- def slice(from: Int, until: Int): Repr = sliceWithKnownBound(from max 0, until)
+ def slice(from: Int, until: Int): Repr = sliceWithKnownBound(math.max(from, 0), until)
// Precondition: from >= 0, until > 0, builder already configured for building.
private[this] def sliceInternal(from: Int, until: Int, b: Builder[A, Repr]): Repr = {
diff --git a/src/library/scala/collection/immutable/List.scala b/src/library/scala/collection/immutable/List.scala
index c14e24ab47..d8c8268a2e 100644
--- a/src/library/scala/collection/immutable/List.scala
+++ b/src/library/scala/collection/immutable/List.scala
@@ -171,6 +171,12 @@ sealed abstract class List[+A] extends LinearSeq[A]
these
}
+ override def slice(from: Int, until: Int): List[A] = {
+ val lo = math.max(from, 0)
+ if (until <= lo || isEmpty) Nil
+ else this drop lo take (until - lo)
+ }
+
override def takeRight(n: Int): List[A] = {
@tailrec
def loop(lead: List[A], lag: List[A]): List[A] = lead match {
diff --git a/src/library/scala/collection/mutable/ArrayOps.scala b/src/library/scala/collection/mutable/ArrayOps.scala
index dcba9a52a5..99929dd93c 100644
--- a/src/library/scala/collection/mutable/ArrayOps.scala
+++ b/src/library/scala/collection/mutable/ArrayOps.scala
@@ -43,8 +43,7 @@ abstract class ArrayOps[T] extends ArrayLike[T, Array[T]] with CustomParalleliza
repr.getClass.getComponentType.getComponentType.asInstanceOf[Predef.Class[U]]))
override def copyToArray[U >: T](xs: Array[U], start: Int, len: Int) {
- var l = len
- if (repr.length < l) l = repr.length
+ var l = math.min(len, repr.length)
if (xs.length - start < l) l = xs.length - start max 0
Array.copy(repr, 0, xs, start, l)
}
diff --git a/test/scaladoc/javascript/package.html b/test/scaladoc/javascript/package.html
new file mode 100644
index 0000000000..421376db9e
--- /dev/null
+++ b/test/scaladoc/javascript/package.html
@@ -0,0 +1 @@
+dummy
diff --git a/test/scaladoc/javascript/test-index.html b/test/scaladoc/javascript/test-index.html
new file mode 100644
index 0000000000..42cbc8cc09
--- /dev/null
+++ b/test/scaladoc/javascript/test-index.html
@@ -0,0 +1,35 @@
+<html>
+ <head>
+ <link rel="stylesheet" type="text/css" media="screen"
+ href="http://code.jquery.com/qunit/git/qunit.css" />
+ <script type="text/javascript"
+ src="http://code.jquery.com/qunit/git/qunit.js"></script>
+ <script type="text/javascript"
+ src="../../../src/compiler/scala/tools/nsc/doc/html/resource/lib/jquery.js"></script>
+ <script src="../../../src/compiler/scala/tools/nsc/doc/html/resource/lib/jquery.layout.js"></script>
+ <script src="../../../src/compiler/scala/tools/nsc/doc/html/resource/lib/scheduler.js"></script>
+ <script type="text/javascript"
+ src="../../../src/compiler/scala/tools/nsc/doc/html/resource/lib/index.js"></script>
+ </head>
+ <body>
+ <h1 id="qunit-header">QUnit example</h1>
+ <h2 id="qunit-banner"></h2>
+ <div id="qunit-testrunner-toolbar"></div>
+ <h2 id="qunit-userAgent"></h2>
+ <ol id="qunit-tests"></ol>
+ <div id="qunit-fixture"></div>
+ <div id="browser" class="ui-layout-west">
+ <div class="ui-west-center">
+ <div id="tpl">
+ <ol class="templates">
+ <li>template</li>
+ </ol>
+ </div>
+ </div>
+ </div>
+ <div id="content" class="ui-layout-center">
+ <iframe name="template"></iframe>
+ </div>
+ <script type="text/javascript" src="test-index.js"></script>
+ </body>
+</html>
diff --git a/test/scaladoc/javascript/test-index.js b/test/scaladoc/javascript/test-index.js
new file mode 100644
index 0000000000..121366c931
--- /dev/null
+++ b/test/scaladoc/javascript/test-index.js
@@ -0,0 +1,17 @@
+Index.PACKAGES = { pkg1: [ { 'class': 'pkg1/Foo.html', name: 'pkg1.Foo' } ] };
+
+asyncTest('Trac #4463 - kindFilter', function () {
+ setTimeout(function () {
+ start();
+
+ equal($('#tpl ol.templates:visible').size(), 1);
+
+ kindFilter('packs');
+ equal($('#tpl ol.templates:visible').size(), 0);
+ equal($('#tpl li.pack a.packhide').text(), 'show');
+
+ kindFilter('all');
+ equal($('#tpl ol.templates:visible').size(), 1);
+ equal($('#tpl li.pack a.packhide').text(), 'hide');
+ }, 1000);
+});