summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2009-10-09 21:25:27 +0000
committerPaul Phillips <paulp@improving.org>2009-10-09 21:25:27 +0000
commitcce8ae3c86acf7624e9d9943cc8a1347560e2eac (patch)
treee064d4c90d8521ad361f332f0a6d44dcf848d722 /src
parente7763d39da01c0394f1dc602167fd29c5b972d94 (diff)
downloadscala-cce8ae3c86acf7624e9d9943cc8a1347560e2eac.tar.gz
scala-cce8ae3c86acf7624e9d9943cc8a1347560e2eac.tar.bz2
scala-cce8ae3c86acf7624e9d9943cc8a1347560e2eac.zip
Breaking down the matcher's various Mix* classe...
Breaking down the matcher's various Mix* classes into direct expressions of condition/success/failure.
Diffstat (limited to 'src')
-rw-r--r--src/compiler/scala/tools/nsc/ast/TreeDSL.scala2
-rw-r--r--src/compiler/scala/tools/nsc/matching/ParallelMatching.scala125
2 files changed, 60 insertions, 67 deletions
diff --git a/src/compiler/scala/tools/nsc/ast/TreeDSL.scala b/src/compiler/scala/tools/nsc/ast/TreeDSL.scala
index 7093af1cd6..c5cef0dd32 100644
--- a/src/compiler/scala/tools/nsc/ast/TreeDSL.scala
+++ b/src/compiler/scala/tools/nsc/ast/TreeDSL.scala
@@ -186,6 +186,8 @@ trait TreeDSL {
if (target.tpe.typeSymbol == SomeClass) TRUE // is Some[_]
else NOT(ID(target) DOT nme.isEmpty) // is Option[_]
+ def GET() = fn(ID(target), nme.get)
+
// name of nth indexed argument to a method (first parameter list), defaults to 1st
def ARG(idx: Int = 0) = Ident(target.paramss.head(idx))
def ARGS = target.paramss.head
diff --git a/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala b/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala
index 1ad78369b5..46f8c8bfbe 100644
--- a/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala
+++ b/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala
@@ -26,7 +26,7 @@ trait ParallelMatching extends ast.TreeDSL
self: ExplicitOuter =>
import global.{ typer => _, _ }
- import definitions.{ AnyRefClass, IntClass, getProductArgs, productProj }
+ import definitions.{ AnyRefClass, IntClass, BooleanClass, getProductArgs, productProj }
import treeInfo.{ isStar }
import CODE._
import Types._
@@ -245,17 +245,17 @@ 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: Guard, guardedRest: Rep, bx: Int) extends RuleApplicationFormal {
def pmatch: PatternMatch = impossible
def rest: Rep = guardedRest
+ lazy val cond = if (guard.isEmpty) TRUE else guard.duplicate.tree
+ lazy val success = requestBody(bx, subst)
+ lazy val failure = guardedRest.toTree
+
final def tree(): Tree = {
- def body = requestBody(bx, subst)
- def guardTest = IF (guard.duplicate.tree) THEN body ELSE guardedRest.toTree
implicit val ctx = context
-
- if (guard.isEmpty) body
- else squeezedBlock(subst.infoForAll.patternValDefs, guardTest)
+ squeezedBlock(subst.infoForAll.patternValDefs, codegen)
}
}
@@ -267,6 +267,9 @@ trait ParallelMatching extends ast.TreeDSL
val literals = pmatch.ps
val defaultPattern = pmatch.defaultPattern
+ private lazy val target: Tree =
+ if (!scrut.tpe.isInt) scrut.id DOT nme.toInt else scrut.id
+
// creates a row transformer for injecting the default case bindings at a given index
private def addDefaultVars(index: Int): Row => Row =
if (defaultVars.isEmpty) identity
@@ -276,14 +279,23 @@ trait ParallelMatching extends ast.TreeDSL
private def rebindAll(r: Row, vs: Iterable[Symbol], tvar: Symbol) =
r rebind r.subst.add(vs, tvar)
+ private def bindVars(Tag: Int, orig: Bindings): Bindings = {
+ def myBindVars(rest: List[(Int, List[Symbol])], bnd: Bindings): Bindings = rest match {
+ case Nil => bnd
+ case (Tag,vs)::xs => myBindVars(xs, bnd.add(vs, scrut.sym))
+ case (_, vs)::xs => myBindVars(xs, bnd)
+ }
+ myBindVars(varMap, orig)
+ }
+
// bound vars and rows for default pattern (only one row, but a list is easier to use later)
- val (defaultVars, defaultRows) = defaultPattern match {
+ lazy val (defaultVars, defaultRows) = defaultPattern match {
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.
- val (literalMap, varMap) = {
+ lazy val (literalMap, varMap) = {
val tags = literals map (_.intValue)
val varMap = tags zip (literals map (_.definedVars))
val litMap =
@@ -295,62 +307,43 @@ trait ParallelMatching extends ast.TreeDSL
(litMap, varMap)
}
- final def tree(): Tree = {
- // Just a demo of breakIf
- // Interpreter.breakIf(true, "lits" -> literals, "mixlit" -> this, literalMap)
-
- def bindVars(Tag: Int, orig: Bindings): Bindings = {
- def myBindVars(rest: List[(Int, List[Symbol])], bnd: Bindings): Bindings = rest match {
- case Nil => bnd
- case (Tag,vs)::xs => myBindVars(xs, bnd.add(vs, scrut.sym))
- case (_, vs)::xs => myBindVars(xs, bnd)
- }
- myBindVars(varMap, orig)
- }
+ lazy val cases =
+ for ((tag, indices) <- literalMap.toList) yield {
+ val newRows = indices map (i => addDefaultVars(i)(rest rows i))
+ val r = make(rest.tvars, newRows ::: defaultRows)
+ val r2 = make(r.tvars, r.rows map (x => x rebind bindVars(tag, x.subst)))
- val cases =
- for ((tag, indices) <- literalMap.toList) yield {
- val newRows = indices map (i => addDefaultVars(i)(rest rows i))
- val r = make(rest.tvars, newRows ::: defaultRows)
- val r2 = make(r.tvars, r.rows map (x => x rebind bindVars(tag, x.subst)))
+ CASE(Literal(tag)) ==> r2.toTree
+ }
- CASE(Literal(tag)) ==> r2.toTree
- }
+ lazy val defaultTree = make(rest.tvars, defaultRows).toTree
+ def casesWithDefault = cases ::: List(CASE(WILD(IntClass.tpe)) ==> defaultTree)
- val defaultTree = make(rest.tvars, defaultRows).toTree
- def casesWithDefault = cases ::: List(CASE(WILD(IntClass.tpe)) ==> defaultTree)
-
- cases match {
- case List(CaseDef(lit, _, body)) =>
- // only one case becomes if/else
- IF (scrut.id MEMBER_== lit) THEN body ELSE defaultTree
- case _ =>
- // otherwise cast to an Int if necessary and run match
- val target: Tree = if (!scrut.tpe.isInt) scrut.id DOT nme.toInt else scrut.id
- target MATCH (casesWithDefault: _*)
- }
+ // only one case becomes if/else, otherwise match
+ def tree() = cases match {
+ case List(CaseDef(lit, _, body)) => IF (scrut.id MEMBER_== lit) THEN body ELSE defaultTree
+ case _ => target MATCH (casesWithDefault: _*)
}
}
/** mixture rule for unapply pattern
*/
- class MixUnapply(val pmatch: PatternMatch, val rest: Rep, typeTest: Boolean) extends RuleApplication {
+ class MixUnapply(val pmatch: PatternMatch, val rest: Rep, typeTest: Boolean) extends RuleApplicationFormal {
val uapattern = head match { case x: UnapplyPattern => x ; case _ => abort("XXX") }
val ua @ UnApply(app, args) = head.tree
- lazy val zipped = pmatch pzip rest.rows
+ private lazy val zipped = pmatch pzip rest.rows
// Note: trailingArgs is not necessarily Nil, because unapply can take implicit parameters.
val Apply(fxn, _ :: trailingArgs) = app
+ def unapplyReturnType = if (args.isEmpty) BooleanClass.tpe else app.tpe typeArgs 0
- lazy val unapplyVar = newVar(ua.pos, app.tpe, scrut.flags)
- lazy val unapplyRHS = Apply(fxn, scrut.id :: trailingArgs) setType unapplyVar.tpe
- lazy val unapplyCall = typedValDef(unapplyVar, unapplyRHS)
+ lazy val unapplyVar = newVar(ua.pos, app.tpe, scrut.flags)
+ lazy val unapplyValDef =
+ typedValDef(unapplyVar, Apply(fxn, scrut.id :: trailingArgs) setType unapplyVar.tpe)
- /** Create a Boolean representing whether the unapply succeeded */
- def unapplyToCond(t: Tree): Tree =
- if (unapplyCall.symbol.tpe.isBoolean) ID(t.symbol)
- else t.symbol IS_DEFINED
+ def mkGet(s: Symbol) = typedValDef(s, fn(ID(unapplyVar), nme.get))
+ def mkVar(tpe: Type) = newVar(ua.pos, tpe, scrut.flags)
// XXX in transition.
object sameUnapplyCall {
@@ -374,25 +367,26 @@ trait ParallelMatching extends ast.TreeDSL
case sameUnapplyCall(args) => r.insert2(toPats(sameFilter(args)) ::: List(NoPattern), pat.boundVariables, scrut.sym)
case _ => r insert (emptyPatterns(dum) ::: List(pat))
}
- def mkGet(s: Symbol) = typedValDef(s, fn(ID(unapplyVar), nme.get))
- def mkVar(tpe: Type) = newVar(ua.pos, tpe, scrut.flags)
- final def tree() = {
- val failRows = zipped.tail filterNot (x => isSameUnapply(x._1)) map { case (pat, r) => r insert pat }
+ lazy val cond: Tree = {
+ val s = unapplyValDef.symbol
+ if (s.tpe.isBoolean) ID(s)
+ else s IS_DEFINED
+ }
- // 0 args => Boolean, 1 => Option[T], >1 => Option[? <: ProductN[T1,...,Tn]]
+ lazy val failure =
+ mkFail(zipped.tail filterNot (x => isSameUnapply(x._1)) map { case (pat, r) => r insert pat })
+ lazy val success = {
val (vdefs, ntemps, nrows) =
args.length match {
case 0 =>
(Nil, Nil, mkNewRows((xs) => Nil, 0))
case 1 =>
- val vsym = mkVar(app.tpe typeArgs 0)
- val nrows = mkNewRows(xs => List(xs.head), 1)
- val vdef = mkGet(vsym)
-
- (List(vdef), List(vsym), nrows)
+ val lhs = mkVar(app.tpe typeArgs 0)
+ val vdef = mkGet(lhs)
+ (List(vdef), List(lhs), mkNewRows(xs => List(xs.head), 1))
case _ =>
val uresGet = mkVar(app.tpe typeArgs 0)
@@ -412,15 +406,12 @@ trait ParallelMatching extends ast.TreeDSL
(vdefHead :: vdefs, vsyms, nrows)
}
- val cond = unapplyToCond(unapplyCall)
- val success = make(ntemps ::: scrut.sym :: rest.tvars, nrows).toTree
- val failure = mkFail(failRows)
-
- squeezedBlock(
- List(handleOuter(unapplyCall)),
- IF (cond) THEN squeezedBlock(vdefs, success) ELSE failure
- )
+ val srep = make(ntemps ::: scrut.sym :: rest.tvars, nrows).toTree
+ squeezedBlock(vdefs, srep)
}
+
+ final def tree() =
+ squeezedBlock(List(handleOuter(unapplyValDef)), codegen)
}
/** handle sequence pattern and ArrayValue (but not star patterns)