summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid MacIver <david.maciver@gmail.com>2008-11-04 22:36:38 +0000
committerDavid MacIver <david.maciver@gmail.com>2008-11-04 22:36:38 +0000
commita96b0d528f88e3abadd9c46e9f5323b814e65f3e (patch)
treebea1b55055ea708c79e458bf717a2afbdc369713
parent2e1a0d99b58b1876db9d03878fc5ffb0761add76 (diff)
downloadscala-a96b0d528f88e3abadd9c46e9f5323b814e65f3e.tar.gz
scala-a96b0d528f88e3abadd9c46e9f5323b814e65f3e.tar.bz2
scala-a96b0d528f88e3abadd9c46e9f5323b814e65f3e.zip
Reverting my previous changes as they seem to b...
Reverting my previous changes as they seem to break things massively and I can't pinpoint how at the moment.
-rw-r--r--src/compiler/scala/tools/nsc/Settings.scala1
-rw-r--r--src/compiler/scala/tools/nsc/matching/CodeFactory.scala105
-rw-r--r--src/compiler/scala/tools/nsc/matching/ParallelMatching.scala16
-rw-r--r--src/compiler/scala/tools/nsc/matching/TransMatcher.scala2
4 files changed, 111 insertions, 13 deletions
diff --git a/src/compiler/scala/tools/nsc/Settings.scala b/src/compiler/scala/tools/nsc/Settings.scala
index d219613df3..add169ad53 100644
--- a/src/compiler/scala/tools/nsc/Settings.scala
+++ b/src/compiler/scala/tools/nsc/Settings.scala
@@ -146,6 +146,7 @@ class Settings(error: String => Unit) {
val Xshowtrees = BooleanSetting ("-Yshow-trees", "Show detailed trees when used in connection with -print:phase").hideToIDE
val skip = PhasesSetting ("-Yskip", "Skip")
+ val Xsqueeze = ChoiceSetting ("-Ysqueeze", "if on, creates compact code in matching", List("on","on","off"), "on").hideToIDE
val statistics = BooleanSetting ("-Ystatistics", "Print compiler statistics").hideToIDE
val stop = PhasesSetting ("-Ystop", "Stop after phase")
val Xwarndeadcode = BooleanSetting ("-Ywarn-dead-code", "Emit warnings for dead code")
diff --git a/src/compiler/scala/tools/nsc/matching/CodeFactory.scala b/src/compiler/scala/tools/nsc/matching/CodeFactory.scala
index 029ccadfa8..d072590d70 100644
--- a/src/compiler/scala/tools/nsc/matching/CodeFactory.scala
+++ b/src/compiler/scala/tools/nsc/matching/CodeFactory.scala
@@ -73,7 +73,7 @@ trait CodeFactory {
Apply(Select(sel, ntpe.member(nme.lengthCompare)), List(Literal(Constant(i)))),
Literal(Constant(0))
)
- )
+ )/*defs.Seq_length ?*/
/** for tree of sequence type sel, returns boolean tree testing that length >= i
*/
@@ -81,12 +81,25 @@ trait CodeFactory {
GreaterThanOrEquals(
typer.typed(Apply(Select(sel, tpe.member(nme.lengthCompare)), List(Literal(Constant(i))))),
typer.typed(Literal(Constant(0))))
+ //defs.Seq_length instead of tpe.member ?
- final def Not(arg:Tree) =
- Select(arg, definitions.Boolean_not)
+ final def Not(arg:Tree) = arg match {
+ case Literal(Constant(true)) => Literal(Constant(false))
+ case Literal(Constant(false)) => Literal(Constant(true))
+ case t => Select(arg, definitions.Boolean_not)
+ }
- def And(left: Tree, right: Tree): Tree =
- Apply(Select(left, definitions.Boolean_and), List(right))
+ def And(left: Tree, right: Tree): Tree = left match {
+ case Literal(Constant(value: Boolean)) =>
+ if (value) right else left
+ case _ =>
+ right match {
+ case Literal(Constant(true)) =>
+ left
+ case _ =>
+ Apply(Select(left, definitions.Boolean_and), List(right))
+ }
+ }
final def Equals(left: Tree, right: Tree): Tree =
Apply(Select(left, nme.EQ), List(right))
@@ -115,4 +128,86 @@ trait CodeFactory {
final def Get(tree : Tree)
= Apply(Select(tree, nme.get), List())
+ // statistics
+ var nremoved = 0
+ var nsubstituted = 0
+
+ final def squeezedBlock(vds: List[Tree], exp: Tree)(implicit theOwner: Symbol): Tree =
+ if (settings_squeeze)
+ squeezedBlock1(vds, exp)
+ else
+ Block(vds,exp)
+
+ final def squeezedBlock1(vds: List[Tree], exp: Tree)(implicit theOwner: Symbol): Tree = {
+ val tpe = exp.tpe
+
+ class RefTraverser(sym: Symbol) extends Traverser {
+ var nref = 0
+ var 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) =>
+ var args1 = args; while(args1 ne Nil) {
+ if(args1.head.symbol eq sym) {
+ nref += 2 // will abort traversal, cannot substitute this one
+ args1 = Nil // break
+ } else {
+ args1 = args1.tail
+ }
+ }
+ traverse(rhs)
+ case t if nref > 1 =>
+ // abort, no story to tell
+ case t =>
+ super.traverse(t)
+ }
+ }
+
+ 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 t if stop =>
+ t
+ case t =>
+ super.transform(t)
+ }
+ }
+ vds match {
+ case Nil =>
+ exp
+ case (vd:ValDef) :: rest =>
+ // recurse
+ val exp1 = squeezedBlock(rest, exp)
+
+ val sym = vd.symbol
+ val rt = new RefTraverser(sym)
+ rt.atOwner (theOwner) (rt.traverse(exp1))
+ rt.nref match {
+ case 0 =>
+ nremoved += 1
+ exp1
+ case 1 if rt.nsafeRef == 1 =>
+ nsubstituted += 1
+ new Subst(sym, vd.rhs).transform(exp1)
+ case _ =>
+ exp1 match {
+ case Block(vds2, exp2) => Block(vd::vds2, exp2)
+ case exp2 => Block(vd::Nil, exp2)
+ }
+ }
+ case x::xs =>
+ squeezedBlock(xs, exp) match {
+ case Block(vds2, exp2) => Block(x::vds2, exp2)
+ case exp2 => Block(x::Nil, exp2)
+ }
+ }
+ }
}
+
diff --git a/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala b/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala
index 32309e08d9..baa849d928 100644
--- a/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala
+++ b/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala
@@ -132,7 +132,7 @@ trait ParallelMatching {
val typedElse = repToTree(guardedRest)
val typedIf = typer.typed { If(guard.duplicate, body, typedElse) }
- typer.typed { Block(vdefs, typedIf) }
+ typer.typed { squeezedBlock(vdefs, typedIf) }
}
}
@@ -309,7 +309,7 @@ trait ParallelMatching {
typer.typed{ mkIdent(uacall.symbol) }
else
emptynessCheck(uacall.symbol)
- typer.typed { Block(List(rep.handleOuter(uacall)), If(cond,Block(vdefs,succ),fail)) }
+ typer.typed { squeezedBlock(List(rep.handleOuter(uacall)), If(cond,squeezedBlock(vdefs,succ),fail)) }
}
}
@@ -372,7 +372,7 @@ trait ParallelMatching {
// fixed length
val cond = getCond(treeAsSeq, xs.length)
return ({thenp:Tree => {elsep:Tree =>
- If(cond, Block(bindings, thenp), elsep)}}, succRep, failRep)
+ If(cond, squeezedBlock(bindings, thenp), elsep)}}, succRep, failRep)
}
// lengthArg is exact length
@@ -588,7 +588,7 @@ trait ParallelMatching {
if (casted ne this.scrutinee)
vdefs = ValDef(casted, gen.mkAsInstanceOf(mkIdent(this.scrutinee), casted.tpe)) :: vdefs
- return typer.typed( If(cond, Block(vdefs, succ), fail) )
+ return typer.typed( If(cond, squeezedBlock(vdefs, succ), fail) )
}
}
@@ -646,7 +646,7 @@ trait ParallelMatching {
override def transform(tree:Tree): Tree = tree match {
case blck @ Block(vdefs, ld @ LabelDef(name,params,body)) =>
val bx = labelIndex(ld.symbol)
- if (bx >= 0 && !isReachedTwice(bx)) Block(vdefs,body)
+ if (bx >= 0 && !isReachedTwice(bx)) squeezedBlock(vdefs,body)
else blck
case If(cond, Literal(Constant(true)), Literal(Constant(false))) =>
@@ -698,8 +698,8 @@ trait ParallelMatching {
labels(bx) = label
return body match {
- case _: Throw | _: Literal => Block(vdefs, body.duplicate setType tpe)
- case _ => Block(vdefs.reverse, LabelDef(label, vsyms, body setType tpe))
+ case _: Throw | _: Literal => squeezedBlock(vdefs, body.duplicate setType tpe)
+ case _ => squeezedBlock(vdefs.reverse, LabelDef(label, vsyms, body setType tpe))
}
}
@@ -724,7 +724,7 @@ trait ParallelMatching {
body match {
case _: Throw | _: Literal => // might be bound elsewhere (see `x @ unapply')
val vdefs = for (v <- vss(bx) ; val substv = subst(v) ; if substv ne null) yield typedValDef(v, substv)
- Block(vdefs, body.duplicate setType resultType)
+ squeezedBlock(vdefs, body.duplicate setType resultType)
case _ =>
Apply(mkIdent(label),args)
}
diff --git a/src/compiler/scala/tools/nsc/matching/TransMatcher.scala b/src/compiler/scala/tools/nsc/matching/TransMatcher.scala
index e96de6a0d5..2772cb5edb 100644
--- a/src/compiler/scala/tools/nsc/matching/TransMatcher.scala
+++ b/src/compiler/scala/tools/nsc/matching/TransMatcher.scala
@@ -23,6 +23,7 @@ trait TransMatcher { self: transform.ExplicitOuter with PatternNodes with Parall
// cache these
final val settings_debug = settings.debug.value
+ final val settings_squeeze = settings.Xsqueeze.value == "on"
// check special case Seq(p1,...,pk,_*)
protected def isRightIgnoring(p: ArrayValue): Boolean = {
@@ -81,6 +82,7 @@ trait TransMatcher { self: transform.ExplicitOuter with PatternNodes with Parall
val mch = typer.typed(repToTree(irep))
var dfatree = typer.typed(Block(vds, mch))
+ // cannot use squeezedBlock because of side-effects, see t275
for ((cs, bx) <- cases.zipWithIndex)
if (!rep.isReached(bx)) cunit.error(cs.body.pos, "unreachable code")