summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-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
19 files changed, 228 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)
}