summaryrefslogtreecommitdiff
path: root/src/compiler
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2009-10-10 00:31:27 +0000
committerPaul Phillips <paulp@improving.org>2009-10-10 00:31:27 +0000
commit422ad71e10f559839ffa0fbd9a4c8dc721210986 (patch)
treef25365ce9d5e5984db4ab995dddac20d800c1e67 /src/compiler
parent1c67c5b849d57a3fae89c4156f4a15defceccbf4 (diff)
downloadscala-422ad71e10f559839ffa0fbd9a4c8dc721210986.tar.gz
scala-422ad71e10f559839ffa0fbd9a4c8dc721210986.tar.bz2
scala-422ad71e10f559839ffa0fbd9a4c8dc721210986.zip
Starting the process of properly encapsulating ...
Starting the process of properly encapsulating the temporary variables created during pattern match translation.
Diffstat (limited to 'src/compiler')
-rw-r--r--src/compiler/scala/tools/nsc/matching/Matrix.scala36
-rw-r--r--src/compiler/scala/tools/nsc/matching/ParallelMatching.scala75
-rw-r--r--src/compiler/scala/tools/nsc/matching/TransMatcher.scala20
3 files changed, 82 insertions, 49 deletions
diff --git a/src/compiler/scala/tools/nsc/matching/Matrix.scala b/src/compiler/scala/tools/nsc/matching/Matrix.scala
index 07923059c1..c5373f0924 100644
--- a/src/compiler/scala/tools/nsc/matching/Matrix.scala
+++ b/src/compiler/scala/tools/nsc/matching/Matrix.scala
@@ -17,6 +17,7 @@ trait Matrix extends MatrixAdditions {
import analyzer.Typer
import CODE._
import Debug._
+ import Flags.{ TRANS_FLAG }
/** Translation of match expressions.
*
@@ -89,6 +90,41 @@ trait Matrix extends MatrixAdditions {
matchResultType: Type) // the expected result type of the whole match
extends Squeezer
{
+ private def ifNull[T](x: T, alt: T) = if (x == null) alt else x
+
+ // TRANS_FLAG communicates there should be no exhaustiveness checking
+ private def flags(checked: Boolean) = if (checked) Nil else List(TRANS_FLAG)
+
+ /** Given a tree, creates a new synthetic variable of the same type
+ * and assigns the tree to it.
+ */
+ def copyVar(
+ root: Tree,
+ _tpe: Type = null,
+ checked: Boolean = false,
+ label: String = "temp"): PatternVar =
+ {
+ val tpe = ifNull(_tpe, root.tpe)
+ val name = newName(root.pos, label)
+ val sym = newVar(root.pos, tpe, flags(checked), name)
+
+ new PatternVar(sym, root)
+ }
+
+ /** The rhs is expressed as a function of the lhs. */
+ def createVar(tpe: Type, f: Symbol => Tree, checked: Boolean = false) = {
+ val lhs = newVar(owner.pos, tpe, flags(checked))
+ val rhs = f(lhs)
+
+ new PatternVar(lhs, rhs)
+ }
+
+ class PatternVar(val lhs: Symbol, val rhs: Tree) {
+ lazy val ident = ID(lhs)
+ lazy val valDef = typedValDef(lhs, rhs)
+ // lazy val valDef = typedValDef(lhs, rhs setType lhs.tpe)
+ }
+
def newVar(
pos: Position,
tpe: Type,
diff --git a/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala b/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala
index 46f8c8bfbe..8c15f7ae08 100644
--- a/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala
+++ b/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala
@@ -31,6 +31,7 @@ trait ParallelMatching extends ast.TreeDSL
import CODE._
import Types._
import Debug._
+ import Flags.{ TRANS_FLAG }
/** Transition **/
def isRightIgnoring(t: Tree) = cond(unbind(t)) { case ArrayValue(_, xs) if !xs.isEmpty => isStar(xs.last) }
@@ -92,7 +93,7 @@ trait ParallelMatching extends ast.TreeDSL
* Note that we only ever match on Symbols, not Trees: a temporary variable
* is created for any expressions being matched on.
*/
- case class Scrutinee(val sym: Symbol) {
+ class Scrutinee(val sym: Symbol) {
import definitions._
// presenting a face of our symbol
@@ -117,7 +118,11 @@ trait ParallelMatching extends ast.TreeDSL
def newVarOfElemType = newVar(pos, elemType)
// for propagating "unchecked" to synthetic vars
- def flags: List[Long] = List(Flags.TRANS_FLAG) filter (sym hasFlag _)
+ def isChecked = !(sym hasFlag TRANS_FLAG)
+ def flags: List[Long] = List(TRANS_FLAG) filter (sym hasFlag _)
+
+ // this is probably where this actually belongs
+ def createVar(tpe: Type, f: Symbol => Tree) = context.createVar(tpe, f, isChecked)
def castedTo(headType: Type) =
if (tpe =:= headType) this
@@ -332,18 +337,17 @@ trait ParallelMatching extends ast.TreeDSL
val uapattern = head match { case x: UnapplyPattern => x ; case _ => abort("XXX") }
val ua @ UnApply(app, args) = head.tree
- 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
+ private def reapply = Apply(fxn, scrut.id :: trailingArgs)
- lazy val unapplyVar = newVar(ua.pos, app.tpe, scrut.flags)
- lazy val unapplyValDef =
- typedValDef(unapplyVar, Apply(fxn, scrut.id :: trailingArgs) setType unapplyVar.tpe)
+ private lazy val zipped = pmatch pzip rest.rows
- def mkGet(s: Symbol) = typedValDef(s, fn(ID(unapplyVar), nme.get))
- def mkVar(tpe: Type) = newVar(ua.pos, tpe, scrut.flags)
+ lazy val unapplyResult =
+ createVar(app.tpe,
+ lhs => reapply setType lhs.tpe,
+ scrut.isChecked
+ )
// XXX in transition.
object sameUnapplyCall {
@@ -369,7 +373,7 @@ trait ParallelMatching extends ast.TreeDSL
}
lazy val cond: Tree = {
- val s = unapplyValDef.symbol
+ val s = unapplyResult.valDef.symbol
if (s.tpe.isBoolean) ID(s)
else s IS_DEFINED
}
@@ -377,41 +381,40 @@ trait ParallelMatching extends ast.TreeDSL
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))
+ private def doSuccess: (List[Tree], List[Symbol], List[Row]) = {
+ def mkVar(tpe: Type) = newVar(ua.pos, tpe, scrut.flags)
- case 1 =>
- val lhs = mkVar(app.tpe typeArgs 0)
- val vdef = mkGet(lhs)
- (List(vdef), List(lhs), mkNewRows(xs => List(xs.head), 1))
+ lazy val lhs = mkVar(app.tpe typeArgs 0)
+ lazy val vdef = typedValDef(lhs, fn(ID(unapplyResult.lhs), nme.get))
- case _ =>
- val uresGet = mkVar(app.tpe typeArgs 0)
- val vdefHead = mkGet(uresGet)
- val ts = getProductArgs(uresGet.tpe).get
- val nrows = mkNewRows(identity, ts.size)
+ // at this point it's Some[T1,T2...]
+ lazy val tpes = getProductArgs(lhs.tpe).get
- val (vdefs: List[Tree], vsyms: List[Symbol]) = List.unzip(
- for ((vtpe, i) <- ts.zipWithIndex) yield {
- val vchild = mkVar(vtpe)
- val accSym = productProj(uresGet, i+1)
- val rhs = fn(ID(uresGet), accSym)
+ // one allocation per tuple element
+ lazy val allocations =
+ for ((tpe, i) <- tpes.zipWithIndex) yield
+ scrut.createVar(tpe, _ => fn(ID(lhs), productProj(lhs, i + 1)))
- (typedValDef(vchild, rhs), vchild)
- })
+ def vdefs = allocations map (_.valDef)
+ def vsyms = allocations map (_.lhs)
- (vdefHead :: vdefs, vsyms, nrows)
- }
+ // 0 is Boolean, 1 is Option[T], 2+ is Option[(T1,T2,...)]
+ args.length match {
+ case 0 => (Nil, Nil, mkNewRows((xs) => Nil, 0))
+ case 1 => (List(vdef), List(lhs), mkNewRows(xs => List(xs.head), 1))
+ case _ => (vdef :: vdefs, vsyms, mkNewRows(identity, tpes.size))
+ }
+ }
+
+ lazy val success = {
+ val (vdefs, ntemps, rows) = doSuccess
+ val srep = make(ntemps ::: scrut.sym :: rest.tvars, rows).toTree
- val srep = make(ntemps ::: scrut.sym :: rest.tvars, nrows).toTree
squeezedBlock(vdefs, srep)
}
final def tree() =
- squeezedBlock(List(handleOuter(unapplyValDef)), codegen)
+ squeezedBlock(List(handleOuter(unapplyResult.valDef)), codegen)
}
/** handle sequence pattern and ArrayValue (but not star patterns)
diff --git a/src/compiler/scala/tools/nsc/matching/TransMatcher.scala b/src/compiler/scala/tools/nsc/matching/TransMatcher.scala
index 6a31a68989..4d8315530f 100644
--- a/src/compiler/scala/tools/nsc/matching/TransMatcher.scala
+++ b/src/compiler/scala/tools/nsc/matching/TransMatcher.scala
@@ -24,7 +24,6 @@ trait TransMatcher extends ast.TreeDSL with CompactTreePrinter {
import global.{ typer => _, _ }
import analyzer.Typer
import definitions._
- import symtab.Flags
import CODE._
// cunit is set to the current unit in ExplicitOuter's transformUnit,
@@ -45,10 +44,9 @@ trait TransMatcher extends ast.TreeDSL with CompactTreePrinter {
{
import context._
- // TRANS_FLAG communicates that there should be no exhaustiveness checking
- val flags = List(Flags.TRANS_FLAG) filterNot (_ => isChecked)
def matchError(obj: Tree) = atPos(selector.pos)(THROW(MatchErrorClass, obj))
def caseIsOk(c: CaseDef) = cond(c.pat) { case _: Apply | Ident(nme.WILDCARD) => true }
+ def rootTypes = selector.tpe.typeArgs
// this appears to be an attempt at optimizing when all case defs are constructor
// patterns, but I don't think it's correct.
@@ -58,22 +56,18 @@ trait TransMatcher extends ast.TreeDSL with CompactTreePrinter {
// For x match { ... we start with a single root
def singleMatch(): (List[Tree], MatrixInit) = {
- val root: Symbol = newVar(selector.pos, selector.tpe, flags)
- val varDef: Tree = typedValDef(root, selector)
+ val v = copyVar(selector, checked = isChecked)
- (List(varDef), MatrixInit(List(root), cases, matchError(ID(root))))
+ (List(v.valDef), MatrixInit(List(v.lhs), cases, matchError(v.ident)))
}
// For (x, y, z) match { ... we start with multiple roots, called tpXX.
def tupleMatch(app: Apply): (List[Tree], MatrixInit) = {
val Apply(fn, args) = app
- val (roots, vars) = List.unzip(
- for ((arg, typeArg) <- args zip selector.tpe.typeArgs) yield {
- val v = newVar(arg.pos, typeArg, flags, newName(arg.pos, "tp"))
- (v, typedValDef(v, arg))
- }
- )
- (vars, MatrixInit(roots, cases, matchError(treeCopy.Apply(app, fn, roots map ID))))
+ val vs = args zip rootTypes map { case (arg, tpe) => copyVar(arg, tpe, isChecked, "tp") }
+
+ def merror = matchError(treeCopy.Apply(app, fn, vs map (_.ident)))
+ (vs map (_.valDef), MatrixInit(vs map (_.lhs), cases, merror))
}
// sets up top level variables and algorithm input