summaryrefslogtreecommitdiff
path: root/src/compiler
diff options
context:
space:
mode:
authorBurak Emir <emir@epfl.ch>2007-11-16 21:32:26 +0000
committerBurak Emir <emir@epfl.ch>2007-11-16 21:32:26 +0000
commit509410ff39e6ce1abe0b3437ce8d06bafa52ba19 (patch)
tree17620f036b3904c316ed1273a3efbc6ab24098cc /src/compiler
parented73e93b1064d551b4c3baa23b73c854d70e251b (diff)
downloadscala-509410ff39e6ce1abe0b3437ce8d06bafa52ba19.tar.gz
scala-509410ff39e6ce1abe0b3437ce8d06bafa52ba19.tar.bz2
scala-509410ff39e6ce1abe0b3437ce8d06bafa52ba19.zip
fixed bug t0154, changed copyright, changed for...
fixed bug t0154, changed copyright, changed formatting
Diffstat (limited to 'src/compiler')
-rw-r--r--src/compiler/scala/tools/nsc/matching/ParallelMatching.scala690
-rw-r--r--src/compiler/scala/tools/nsc/matching/TransMatcher.scala227
2 files changed, 315 insertions, 602 deletions
diff --git a/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala b/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala
index b65b614de1..896ab12b5a 100644
--- a/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala
+++ b/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala
@@ -1,6 +1,7 @@
/* NSC -- new Scala compiler
* Copyright 2005-2007 LAMP/EPFL
- * @author Burak Emir
+ * Copyright 2007 Google Inc. All Rights Reserved.
+ * Author: bqe@google.com (Burak Emir)
*/
// $Id$
@@ -9,9 +10,10 @@ package scala.tools.nsc.matching
import scala.tools.nsc.util.Position
import collection.mutable.ListBuffer
-/** Translation of Match Expressions
+/** Translation of match expressions.
*
- * `p': pattern
+ * `p': pattern
+ * `g': guard
* `bx': body index
*
* internal representation is (temp:List[Symbol], row:List[Row])
@@ -21,7 +23,6 @@ import collection.mutable.ListBuffer
*
* Row( p_m1 ... p_mn g_m b_m ) + subst
*
- * @author Burak Emir
*/
trait ParallelMatching {
self: transform.ExplicitOuter with PatternNodes with CodeFactory =>
@@ -30,18 +31,26 @@ trait ParallelMatching {
import typer.typed
import symtab.Flags
- /** here, we distinguish which rewrite rule to apply
- * @pre column does not contain alternatives (ensured by initRep)
+ // used as argument to `EqualsPatternClass'
+ case class PseudoType(o: Tree) extends SimpleTypeProxy {
+ override def underlying: Type = o.tpe
+ }
+
+ /** picks which rewrite rule to apply
+ * @precondition: column does not contain alternatives (ensured by initRep)
*/
- def MixtureRule(scrutinee:Symbol, column:List[Tree], rest:Rep)(implicit rep:RepFactory): RuleApplication = {
+ def MixtureRule(scrutinee: Symbol, column: List[Tree], rest: Rep)(implicit rep: RepFactory): RuleApplication = {
def isSimpleSwitch: Boolean = {
- (isSameType(scrutinee.tpe.widen, definitions.IntClass.tpe)||
+ (isSameType(scrutinee.tpe.widen, definitions.IntClass.tpe) ||
isSameType(scrutinee.tpe.widen, definitions.CharClass.tpe)) && {
- var xs = column; while(!xs.isEmpty) { // forall
- val h = xs.head
- if(strip2(h).isInstanceOf[Literal] || isDefaultPattern(h)) { xs = xs.tail } else return false
- }
+ var xs = column; while(!xs.isEmpty) { // forall
+ val h = xs.head
+ if (strip2(h).isInstanceOf[Literal] || isDefaultPattern(h))
+ xs = xs.tail
+ else
+ return false
+ }
return true
}}
@@ -52,7 +61,7 @@ trait ParallelMatching {
}
// true if pattern type is direct subtype of scrutinee (can't use just <:< cause have to take variance into account)
- def directSubtype(ptpe:Type) =
+ def directSubtype(ptpe: Type) =
(ptpe.parents.exists { x => ((x.typeSymbol eq scrutinee.tpe.typeSymbol) && (x <:< scrutinee.tpe))});
// true if each pattern type is case and direct subtype of scrutinee
@@ -63,62 +72,46 @@ trait ParallelMatching {
case t @ Typed(_,tpt) =>
isCaseClass(tpt.tpe) && directSubtype( t.tpe ) && isFlatCases(col.tail)
case Ident(nme.WILDCARD) =>
- isFlatCases(col.tail) // treat col.tail specially?
- case i @ Ident(n) => // n ne nme.WILDCARD
- assert(false)
- ( (i.symbol.flags & Flags.CASE) != 0) && directSubtype( i.tpe ) && isFlatCases(col.tail)
- case s @ Select(_,_) => // i.e. scala.Nil
- assert(false)
- ( (s.symbol.flags & Flags.CASE) != 0) && directSubtype( s.tpe ) && isFlatCases(col.tail)
+ isFlatCases(col.tail) // treat col.tail specially?
case p =>
- //Console.println(p.getClass)
false
}
}
- if(isEqualsPattern(column.head.tpe)) { DBG("\n%%% MixEquals");
+ if (isEqualsPattern(column.head.tpe)) {
return new MixEquals(scrutinee, column, rest)
}
- // the next condition is never true, @see isImplemented/CantHandleSeq
- if(column.head.isInstanceOf[ArrayValue]) {
+ if (column.head.isInstanceOf[ArrayValue]) {
val av = column.head.asInstanceOf[ArrayValue]
- if(!isRightIgnoring(av)) { DBG("\n%%% MixSequence"); return new MixSequence(scrutinee, column, rest) }
- else { DBG("\n%%% MixSequenceStar"); return new MixSequenceStar(scrutinee, column, rest) }
+ return if (!isRightIgnoring(av))
+ new MixSequence(scrutinee, column, rest)
+ else
+ new MixSequenceStar(scrutinee, column, rest)
}
- if(isSimpleSwitch) { DBG("\n%%% MixLiterals")
+ if (isSimpleSwitch) {
return new MixLiterals(scrutinee, column, rest)
}
-
- if(settings_casetags && (column.length > 1) && isFlatCases(column)) {
- //DBG("flat cases!"+column+"\n"+scrutinee.tpe.typeSymbol.children+"\n"+scrutinee.tpe.member(nme.tag))
- DBG("\n%%% MixCases")
+ if (settings_casetags && (column.length > 1) && isFlatCases(column)) {
return new MixCases(scrutinee, column, rest)
- // if(scrutinee.tpe./*?type?*/symbol.hasFlag(symtab.Flags.SEALED)) new MixCasesSealed(scrutinee, column, rest)
- // else new MixCases(scrutinee, column, rest)
}
- //Console.println("isUnapplyHead = "+isUnapplyHead())
- if(isUnapplyHead()) { DBG("\n%%% MixUnapply")
+ if (isUnapplyHead()) {
return new MixUnapply(scrutinee, column, rest)
}
+ return new MixTypes(scrutinee, column, rest)
+ }
- DBG("\n%%% MixTypes")
- return new MixTypes(scrutinee, column, rest) // todo: handle type tests in unapply
- } /* def MixtureRule(scrutinee:Symbol, column:List[Tree], rest:Rep): RuleApplication */
-
- // ---------------------------------- data
-
- sealed abstract class RuleApplication(rep:RepFactory) {
+ sealed abstract class RuleApplication(rep: RepFactory) {
def scrutinee:Symbol
// used in MixEquals and MixSequence
- final protected def repWithoutHead(col:List[Tree],rest:Rep)(implicit theOwner:Symbol): Rep = {
+ final protected def repWithoutHead(col: List[Tree],rest: Rep)(implicit theOwner: Symbol): Rep = {
var fcol = col.tail
var frow = rest.row.tail
val nfailrow = new ListBuffer[Row]
while(fcol ne Nil) {
val p = fcol.head
frow.head match {
- case Row(pats,binds,g,bx) => nfailrow += Row(p::pats,binds,g,bx)
+ case Row(pats, binds, g, bx) => nfailrow += Row(p::pats, binds, g, bx)
}
fcol = fcol.tail
frow = frow.tail
@@ -140,19 +133,19 @@ trait ParallelMatching {
def scrutinee:Symbol = throw new RuntimeException("this never happens")
final def tree(implicit theOwner: Symbol, failTree: Tree): Tree = {
val body = typed { rep.requestBody(bx, subst) }
- if(guard eq EmptyTree)
+ if (guard eq EmptyTree)
return body
val vdefs = targetParams(subst)
val typedElse = repToTree(guardedRest)
- val typedIf = typed{If(guard.duplicate, body, typedElse)}
+ val typedIf = typed { If(guard.duplicate, body, typedElse) }
typer.typed { squeezedBlock(vdefs, typedIf) }
- } /* def tree(implicit theOwner: Symbol, failTree: Tree) */
+ }
}
-
+ /** superclass of mixture rules for case classes and literals (both translated to switch on an integer)
+ */
abstract class CaseRuleApplication(rep:RepFactory) extends RuleApplication(rep) {
-
def column: List[Tree]
def rest:Rep
@@ -162,7 +155,7 @@ trait ParallelMatching {
var theDefaultRows: List[Row] = null
def getDefaultRows: List[Row] = {
- if(theDefaultRows ne null)
+ if (theDefaultRows ne null)
return theDefaultRows
var res:List[Row] = Nil
var ds = defaults; while(ds ne Nil) {
@@ -184,7 +177,7 @@ trait ParallelMatching {
protected def grabTemps: List[Symbol] = rest.temp
protected def grabRow(index:Int): Row = rest.row(index) match {
- case r @ Row(pats, s, g, bx) => if(defaultV.isEmpty) r else {
+ case r @ Row(pats, s, g, bx) => if (defaultV.isEmpty) r else {
val vs = strip1(column(index)) // get vars
val nbindings = s.add(vs.elements,scrutinee)
Row(pats, nbindings, g, bx)
@@ -194,13 +187,13 @@ trait ParallelMatching {
/** inserts row indices using in to list of tagindexpairs*/
protected def tagIndicesToReps(implicit theOwner: Symbol) = {
val defaultRows = getDefaultRows
- var trs:List[(Int,Rep)] = Nil
+ var trs: List[(Int,Rep)] = Nil
var old = tagIndexPairs
- while(tagIndexPairs ne null) { // collect all with same tag
+ while (tagIndexPairs ne null) { // collect all with same tag
val tag = tagIndexPairs.tag
var tagRows = this.grabRow(tagIndexPairs.index)::Nil
tagIndexPairs = tagIndexPairs.next
- while((tagIndexPairs ne null) && tagIndexPairs.tag == tag) {
+ while ((tagIndexPairs ne null) && tagIndexPairs.tag == tag) {
tagRows = this.grabRow(tagIndexPairs.index)::tagRows
tagIndexPairs = tagIndexPairs.next
}
@@ -220,30 +213,29 @@ trait ParallelMatching {
* @return optionally, a default continuation,
**/
def getTransition(implicit theOwner: Symbol): (List[(Int,Rep)],Set[Symbol],Option[Rep]) =
- (tagIndicesToReps, defaultV, {if(haveDefault) Some(defaultsToRep) else None})
- } /* CaseRuleApplication */
+ (tagIndicesToReps, defaultV, {if (haveDefault) Some(defaultsToRep) else None})
+ }
- /**
- * mixture rule for flat case class (using tags)
- *
+ /** mixture rule for flat case class (using tags)
* this rule gets translated to a switch of _.$tag()
**/
class MixCases(val scrutinee:Symbol, val column:List[Tree], val rest:Rep)(implicit rep:RepFactory) extends CaseRuleApplication(rep) {
- /** insert row indices using in to list of tagindexpairs */
+ /** insert row indices into list of tagindexpairs */
{
var xs = column; var i = 0; while(xs ne Nil) { // forall
val p = strip2(xs.head)
- if(isDefaultPattern(p))
- insertDefault(i,strip1(xs.head))
+ if (isDefaultPattern(p))
+ insertDefault(i, strip1(xs.head))
else
- insertTagIndexPair( getCaseTag(p.tpe), i)
+ insertTagIndexPair(getCaseTag(p.tpe), i)
i += 1
xs = xs.tail
}
}
override def grabTemps = scrutinee::rest.temp
+
override def grabRow(index:Int) = rest.row(tagIndexPairs.index) match {
case Row(pats, s, g, bx) =>
val nbindings = s.add(strip1(column(index)).elements, scrutinee)
@@ -252,9 +244,8 @@ trait ParallelMatching {
final def tree(implicit theOwner: Symbol, failTree: Tree): Tree = {
val (branches, defaultV, default) = getTransition // tag body pairs
- //DBG("[[mix cases transition: branches \n"+(branches.mkString("","\n","")+"\ndefaults:"+defaultV+" "+default+"]]"))
- var ndefault = if(default.isEmpty) failTree else repToTree(default.get)
+ var ndefault = if (default.isEmpty) failTree else repToTree(default.get)
var cases = branches map {
case (tag, r) =>
CaseDef(Literal(tag),
@@ -262,7 +253,7 @@ trait ParallelMatching {
{
val pat = this.column(this.tagIndexPairs.find(tag));
val ptpe = pat.tpe
- if(this.scrutinee.tpe.typeSymbol.hasFlag(symtab.Flags.SEALED) && strip2(pat).isInstanceOf[Apply]) {
+ if (this.scrutinee.tpe.typeSymbol.hasFlag(symtab.Flags.SEALED) && strip2(pat).isInstanceOf[Apply]) {
//cast
val vtmp = newVar(pat.pos, ptpe)
squeezedBlock(
@@ -273,10 +264,8 @@ trait ParallelMatching {
}
)}
- //?renamingBind(defaultV, this.scrutinee, ndefault) // each v in defaultV gets bound to scrutinee
-
// make first case a default case.
- if(this.scrutinee.tpe.typeSymbol.hasFlag(symtab.Flags.SEALED) && defaultV.isEmpty) {
+ if (this.scrutinee.tpe.typeSymbol.hasFlag(symtab.Flags.SEALED) && defaultV.isEmpty) {
ndefault = cases.head.body
cases = cases.tail
}
@@ -284,47 +273,34 @@ trait ParallelMatching {
cases.length match {
case 0 => ndefault
case 1 => val CaseDef(lit,_,body) = cases.head
- If(Equals(Select(mkIdent(this.scrutinee),nme.tag),lit), body, ndefault)
+ If(Equals(Select(mkIdent(this.scrutinee), nme.tag), lit), body, ndefault)
case _ => val defCase = CaseDef(mk_(definitions.IntClass.tpe), EmptyTree, ndefault)
Match(Select(mkIdent(this.scrutinee),nme.tag), cases ::: defCase :: Nil)
}
- } /* def tree(implicit theOwner: Symbol, failTree: Tree) */
- } /* MixCases */
-
- /**
- * mixture rule for flat case class (using tags)
- *
- * this rule gets translated to a switch of _.$tag()
- class MixCasesSealed(scrut:Symbol, col:List[Tree], res:Rep) extends MixCases(scrut, col, res) {
- override def grabTemps = rest.temp
- override def grabRow(index:Int) = rest.row(tagIndexPairs.index)
+ }
}
- **/
- /**
- * mixture rule for literals
- *
- * this rule gets translated to a switch. all defaults/same literals are collected
- **/
+ /** mixture rule for literals
+ */
class MixLiterals(val scrutinee:Symbol, val column:List[Tree], val rest:Rep)(implicit rep:RepFactory) extends CaseRuleApplication(rep) {
- private var defaultIndexSet: Set64 = if(column.length < 64) new Set64 else null
+ private var defaultIndexSet: Set64 = if (column.length < 64) new Set64 else null
override def insertDefault(tag: Int, vs: Set[Symbol]): Unit =
- if(defaultIndexSet eq null) super.insertDefault(tag,vs)
+ if (defaultIndexSet eq null) super.insertDefault(tag,vs)
else {
defaultIndexSet |= tag
defaultV = defaultV ++ vs
}
protected override def haveDefault: Boolean =
- if(defaultIndexSet eq null) super.haveDefault else (defaultIndexSet.underlying != 0)
+ if (defaultIndexSet eq null) super.haveDefault else (defaultIndexSet.underlying != 0)
override def getDefaultRows: List[Row] = {
- if(theDefaultRows ne null)
+ if (theDefaultRows ne null)
return theDefaultRows
- if(defaultIndexSet eq null)
+ if (defaultIndexSet eq null)
super.getDefaultRows
else {
var ix = 63
@@ -344,18 +320,7 @@ trait ParallelMatching {
private def sanity(pos:Position, tag: Int, pvars:List[Symbol]) {
varMap = (tag,pvars)::varMap
- //if(!pvars.isEmpty) cunit.error(pos, "nonsensical variable binding")
}
- /* // eager
- private def bindVars(Tag:Int, body:Tree): Tree = {
- def myBindVars(rest:List[(Int,List[Symbol])], vd: List[Tree]): Tree = rest match {
- case Nil => if(vd eq Nil) body else Block(vd,body)
- case (Tag,vs)::xs => myBindVars(xs, (vs.map { v => typedValDef(v,mkIdent(scrutinee)) }):::vd)
- case (_, vs)::xs => myBindVars(xs, vd)
- }
- myBindVars(varMap, Nil)
- }
- */
//lazy
private def bindVars(Tag:Int, orig: Binding): Binding = {
def myBindVars(rest:List[(Int,List[Symbol])], bnd: Binding): Binding = rest match {
@@ -382,37 +347,35 @@ trait ParallelMatching {
final def tree(implicit theOwner: Symbol, failTree: Tree): Tree = {
val (branches, defaultV, defaultRepOpt) = this.getTransition // tag body pairs
- DBG("[[mix literal transition: branches \n"+(branches.mkString("","\n",""))+"\ndefaults:"+defaultV+"\n"+defaultRepOpt+"\n]]")
val cases = branches map {
case (tag, r) =>
- val r2 = rep.make(r.temp, r.row map { case Row(pat,bnd,g,bx) => Row(pat,bindVars(tag,bnd),g,bx) })
+ val r2 = rep.make(r.temp, r.row map { case Row(pat, bnd, g, bx) => Row(pat, bindVars(tag, bnd), g, bx) })
val t2 = repToTree(r2)
CaseDef(Literal(tag), EmptyTree, t2)
}
- var ndefault = if(defaultRepOpt.isEmpty) failTree else repToTree(defaultRepOpt.get)
- if(cases.length == 1) {
+ var ndefault = if (defaultRepOpt.isEmpty) failTree else repToTree(defaultRepOpt.get)
+ if (cases.length == 1) {
val CaseDef(lit,_,body) = cases.head
If(Equals(mkIdent(this.scrutinee),lit), body, ndefault)
} else {
val defCase = CaseDef(mk_(definitions.IntClass.tpe), EmptyTree, ndefault)
- return if(isSameType(this.scrutinee.tpe.widen, definitions.CharClass.tpe))
- Match(Select(mkIdent(this.scrutinee), nme.toInt), cases ::: defCase :: Nil)
+ return if (isSameType(this.scrutinee.tpe.widen, definitions.CharClass.tpe))
+ Match(Select(mkIdent(this.scrutinee), nme.toInt), cases ::: defCase :: Nil)
else
- Match(mkIdent(this.scrutinee), cases ::: defCase :: Nil)
+ Match(mkIdent(this.scrutinee), cases ::: defCase :: Nil)
}
- } /* def tree(implicit theOwner: Symbol, failTree: Tree) */
- } /* MixLiterals */
+ }
+ }
- /**
- * mixture rule for unapply pattern
+ /** mixture rule for unapply pattern
*/
- class MixUnapply(val scrutinee:Symbol, val column:List[Tree], val rest:Rep)(implicit rep:RepFactory) extends RuleApplication(rep) {
+ class MixUnapply(val scrutinee: Symbol, val column: List[Tree], val rest: Rep)(implicit rep: RepFactory) extends RuleApplication(rep) {
def newVarCapture(pos:Position,tpe:Type)(implicit theOwner:Symbol) = {
val v = newVar(pos,tpe)
- if(scrutinee.hasFlag(symtab.Flags.TRANS_FLAG))
+ if (scrutinee.hasFlag(symtab.Flags.TRANS_FLAG))
v.setFlag(symtab.Flags.TRANS_FLAG) // propagate "unchecked"
v
}
@@ -420,8 +383,6 @@ trait ParallelMatching {
private def bindToScrutinee(x:Symbol) = typedValDef(x,mkIdent(scrutinee))
val (vs,unapp) = strip(column.head)
- //DBG("\n\n?? vs = "+vs)
- //DBG("?? unapp = "+unapp)
/** returns (unapply-call, success-rep, optional fail-rep*/
final def getTransition(implicit theOwner: Symbol): (Tree, List[Tree], Rep, Option[Rep]) = {
@@ -430,37 +391,41 @@ trait ParallelMatching {
val ures = newVarCapture(ua.pos, app.tpe)
val n = args.length
val uacall = typedValDef(ures, Apply(fn, mkIdent(scrutinee) :: appargs.tail))
- //DBG("uacall:"+uacall)
- val nrowsOther = column.tail.zip(rest.row.tail) flatMap { case (pat, Row(ps, subst, g, bx)) => strip2(pat) match {
- case UnApply(app @ Apply(fn1,_),args) if fn.symbol==fn1.symbol => Nil
- case _ => List(Row(pat::ps, subst, g, bx))
- }}
- val nrepFail = if(nrowsOther.isEmpty) None else Some(rep.make(scrutinee::rest.temp, nrowsOther))
- //DBG("active = "+column.head+" / nrepFail = "+nrepFail)
+ val nrowsOther = column.tail.zip(rest.row.tail) flatMap {
+ case (pat, Row(ps, subst, g, bx)) =>
+ strip2(pat) match {
+ case UnApply(app @ Apply(fn1,_),args) if fn.symbol == fn1.symbol => Nil
+ case _ => List(Row(pat::ps, subst, g, bx))
+ }}
+ val nrepFail = if (nrowsOther.isEmpty) None else Some(rep.make(scrutinee::rest.temp, nrowsOther))
n match {
case 0 => //special case for unapply(), app.tpe is boolean
val ntemps = scrutinee :: rest.temp
- val nrows = column.zip(rest.row) map { case (pat, Row(ps, subst, g, bx)) => strip2(pat) match {
- case UnApply(Apply(fn1,_),args) if (fn.symbol == fn1.symbol) =>
- val nsubst = subst.add(strip1(pat).elements, scrutinee)
- Row(EmptyTree::ps, nsubst /*subst*/ , g, bx)
- case _ =>
- Row( pat ::ps, subst, g, bx)
- }}
- (uacall, Nil, rep.make(ntemps, nrows), nrepFail)
+ val nrows = column.zip(rest.row) map {
+ case (pat, Row(ps, subst, g, bx)) =>
+ strip2(pat) match {
+ case UnApply(Apply(fn1,_),args) if (fn.symbol == fn1.symbol) =>
+ val nsubst = subst.add(strip1(pat).elements, scrutinee)
+ Row(EmptyTree::ps, nsubst, g, bx)
+ case _ =>
+ Row( pat ::ps, subst, g, bx)
+ }}
+ (uacall, Nil, rep.make(ntemps, nrows), nrepFail)
case 1 => //special case for unapply(p), app.tpe is Option[T]
val vtpe = app.tpe.typeArgs(0)
val vsym = newVarCapture(ua.pos, vtpe)
val ntemps = vsym :: scrutinee :: rest.temp
- val nrows = column.zip(rest.row) map { case (pat, Row(ps, subst, g, bx)) => strip2(pat) match {
- case UnApply(Apply(fn1,_),args) if (fn.symbol == fn1.symbol) =>
- val nsubst = subst.add(strip1(pat).elements, scrutinee)
- Row(args(0) :: EmptyTree :: ps, nsubst /*subst*/ , g, bx)
- case _ =>
- Row(EmptyTree :: pat :: ps, subst, g, bx)
- }}
+ val nrows = column.zip(rest.row) map {
+ case (pat, Row(ps, subst, g, bx)) =>
+ strip2(pat) match {
+ case UnApply(Apply(fn1,_),args) if (fn.symbol == fn1.symbol) =>
+ val nsubst = subst.add(strip1(pat).elements, scrutinee)
+ Row(args(0) :: EmptyTree :: ps, nsubst, g, bx)
+ case _ =>
+ Row(EmptyTree :: pat :: ps, subst, g, bx)
+ }}
val vdef = typedValDef(vsym, Select(mkIdent(ures), nme.get))
(uacall, List(vdef), rep.make(ntemps, nrows), nrepFail)
@@ -470,13 +435,12 @@ trait ParallelMatching {
vdefs += typedValDef(uresGet, Select(mkIdent(ures), nme.get))
var ts = definitions.getProductArgs(uresGet.tpe).get
var i = 1;
- //DBG("typeargs"+ts)
val vsyms = new ListBuffer[Symbol]
while(ts ne Nil) {
val vtpe = ts.head
val vchild = newVarCapture(ua.pos, vtpe)
val accSym = definitions.productProj(uresGet, i)
- val rhs = typed(Apply(Select(mkIdent(uresGet), accSym), List())) // nsc !
+ val rhs = typed(Apply(Select(mkIdent(uresGet), accSym), List()))
vdefs += typedValDef(vchild, rhs)
vsyms += vchild
ts = ts.tail
@@ -484,11 +448,11 @@ trait ParallelMatching {
}
val ntemps = vsyms.toList ::: scrutinee :: rest.temp
val dummies = getDummies(i - 1)
- val nrows = column.zip(rest.row) map { case (pat,Row(ps, subst, g, bx)) => strip2(pat) match {
- case UnApply(Apply(fn1,_),args) if (fn.symbol == fn1.symbol) =>
+ val nrows = column.zip(rest.row) map { case (pat, Row(ps, subst, g, bx)) => strip2(pat) match {
+ case UnApply(Apply(fn1, _), args) if (fn.symbol == fn1.symbol) =>
val nsubst = subst.add(strip1(pat).elements, scrutinee)
- Row( args::: EmptyTree ::ps, nsubst /*subst*/ , g, bx)
- case _ =>
+ Row( args::: EmptyTree ::ps, nsubst, g, bx)
+ case _ =>
Row(dummies::: pat ::ps, subst, g, bx)
}}
(uacall, vdefs.toList, rep.make(ntemps, nrows), nrepFail)
@@ -496,24 +460,21 @@ trait ParallelMatching {
} /* def getTransition(...) */
final def tree(implicit theOwner: Symbol, failTree: Tree) = {
- val (uacall/*:ValDef*/ , vdefs,srep,frep) = this.getTransition // uacall is a Valdef
- DBG("getTransition"+(uacall,vdefs,srep,frep))
+ val (uacall , vdefs,srep,frep) = this.getTransition
val succ = repToTree(srep)
- val fail = if(frep.isEmpty) failTree else repToTree(frep.get)
+ val fail = if (frep.isEmpty) failTree else repToTree(frep.get)
val cond =
- if(uacall.symbol.tpe.typeSymbol eq definitions.BooleanClass)
+ if (uacall.symbol.tpe.typeSymbol eq definitions.BooleanClass)
typed{ mkIdent(uacall.symbol) }
else
emptynessCheck(uacall.symbol)
typed { squeezedBlock(List(rep.handleOuter(uacall)), If(cond,squeezedBlock(vdefs,succ),fail)) }
- } /* def tree(implicit theOwner: Symbol, failTree: Tree) */
- } /* MixUnapply */
-
-
+ }
+ }
/** handle sequence pattern and ArrayValue (but not star patterns)
*/
- sealed class MixSequence(val scrutinee:Symbol, val column:List[Tree], val rest:Rep)(implicit rep:RepFactory) extends RuleApplication(rep) {
+ sealed class MixSequence(val scrutinee: Symbol, val column: List[Tree], val rest: Rep)(implicit rep: RepFactory) extends RuleApplication(rep) {
private val sequenceType = scrutinee.tpe.widen.baseType(definitions.SeqClass)
private val elementType = getElemType_Sequence(scrutinee.tpe)
@@ -524,8 +485,8 @@ trait ParallelMatching {
protected def getSubPatterns(len:Int, x:Tree):Option[List[Tree]] = x match {
case av @ ArrayValue(_,xs) if (!isRightIgnoring(av) && xs.length == len) => Some(xs ::: List(EmptyTree))
case av @ ArrayValue(_,xs) if ( isRightIgnoring(av) && xs.length == len+1) => Some(removeStar(xs)) // (*)
- case EmptyTree | Ident(nme.WILDCARD) => Some(getDummies(len+1))
- case _ => None
+ case EmptyTree | Ident(nme.WILDCARD) => Some(getDummies(len+1))
+ case _ => None
}
protected def makeSuccRep(vs:List[Symbol], tail:Symbol, nrows:List[Row])(implicit theOwner: Symbol) =
@@ -534,17 +495,17 @@ trait ParallelMatching {
/** returns true if x is more general than y */
protected def subsumes(x:Tree, y:Tree): Boolean = (x,y) match {
case (av @ ArrayValue(_,xs), bv @ ArrayValue(_,ys)) =>
- isRightIgnoring(av) && !isRightIgnoring(bv) && xs.length == ys.length+1 // (*)
+ isRightIgnoring(av) && !isRightIgnoring(bv) && xs.length == ys.length+1 // see (*)
case _ =>
false
}
// context (to be used in IF), success and failure Rep
- def getTransition(implicit theOwner: Symbol): (Tree => Tree => Tree, Rep, Rep) = {
+ def getTransition(implicit theOwner: Symbol): (Tree => Tree => Tree, Rep, Rep) = {
assert(isSubType(scrutinee.tpe, column.head.tpe), "problem "+scrutinee.tpe+" not <: "+column.head.tpe)
val treeAsSeq =
- if(!isSubType(scrutinee.tpe, column.head.tpe))
+ if (!isSubType(scrutinee.tpe, column.head.tpe))
typed(gen.mkAsInstanceOf(mkIdent(scrutinee), column.head.tpe, true))
else
mkIdent(scrutinee)
@@ -560,57 +521,37 @@ trait ParallelMatching {
//build new temps on which we will match subpatterns
// if is right ignoring, don't want last one
- var ys = if(isRightIgnoring(av)) xs.take(xs.length-1) else xs; while(ys ne Nil) {
+ var ys = if (isRightIgnoring(av)) xs.take(xs.length-1) else xs;
+ while(ys ne Nil) {
val p = strip2(ys.head)
childpats += p
val temp = newVar(p.pos, elementType)
- //DBG("new temp:"+temp+":"+temp.tpe)
- //DBG("seqelem:"+seqElement(treeAsSeq.duplicate, ix))
vs += temp
bindings += typedValDef(temp, seqElement(treeAsSeq.duplicate, ix))
ix += 1
ys = ys.tail
}
val tail = newVar(scrutinee.pos, sequenceType)
- bindings += typedValDef(tail, {if(ix-1>0) seqDrop(treeAsSeq.duplicate, ix) else mkIdent(scrutinee)})
+ bindings += typedValDef(tail, {if (ix-1>0) seqDrop(treeAsSeq.duplicate, ix) else mkIdent(scrutinee)})
val nrows = new ListBuffer[Row]
val frows = new ListBuffer[Row]
- //val childpatList = childpats.toList
var cs = column; var rw = rest.row; while (cs ne Nil) {
(getSubPatterns(ix, cs.head),rw.head) match {
case (Some(ps), Row(pats,subst,g,b)) =>
- nrows += Row( ps ::: pats, subst, g, b)
- if(isDefaultPattern(cs.head) || subsumes(cs.head, av))
- frows += Row( cs.head :: pats, subst, g, b)
- case ( None , Row(pats,subst,g,b) ) =>
+ nrows += Row( ps ::: pats, subst, g, b)
+ if (isDefaultPattern(cs.head) || subsumes(cs.head, av))
frows += Row( cs.head :: pats, subst, g, b)
+ case ( None , Row(pats,subst,g,b) ) =>
+ frows += Row( cs.head :: pats, subst, g, b)
}
cs = cs.tail
rw = rw.tail
}
val succRep = makeSuccRep(vs.toList, tail, nrows.toList)
-
val failRep = rep.make( scrutinee :: rest.temp, frows.toList)
-
- /*
- if(isRightIgnoring(av)) { // contains a _* at the end
- val minlen = xs.length-1;
-
- //typedValDef(casted, treeAsSeq.duplicate) :: bindings
-
- val tempTail = newVar(xs.last.pos, xs.last.tpe)
- bindings += typedValDef(tempTail, seqDrop(treeAsSeq.duplicate, minlen))
-
- val cond = seqLongerThan(treeAsSeq.duplicate, column.head.tpe, minlen)
-
- return ({thenp:Tree => {elsep:Tree =>
- If(cond, squeezedBlock(bindings.toList, thenp), elsep)
- }}, succRep, failRep)
- }
- */
// fixed length
val cond = getCond(treeAsSeq, xs.length)
return ({thenp:Tree => {elsep:Tree => squeezedBlock(bindings.toList,If(cond, thenp, elsep))}}, succRep, failRep)
@@ -622,13 +563,12 @@ trait ParallelMatching {
final def tree(implicit theOwner: Symbol, failTree: Tree) = {
val (cx,srep,frep) = this.getTransition
- //DBG("MSSf:"+srep.toString)
- //DBG("MSSs:"+frep.toString)
val succ = repToTree(srep)
val fail = repToTree(frep)
cx(succ)(fail)
}
}
+
/** handle sequence pattern and ArrayValue (but not star patterns)
*/
final class MixSequenceStar(scrutinee:Symbol, column:List[Tree], rest:Rep)(implicit rep:RepFactory) extends MixSequence(scrutinee,column,rest) {
@@ -647,47 +587,41 @@ trait ParallelMatching {
}
-
override protected def makeSuccRep(vs:List[Symbol], tail:Symbol, nrows:List[Row])(implicit theOwner: Symbol) =
rep.make( vs ::: tail :: scrutinee :: rest.temp, nrows)
// lengthArg is minimal length
override protected def getCond(tree:Tree, lengthArg:Int) = seqLongerThan(tree.duplicate, column.head.tpe, lengthArg - 1)
-
}
// @todo: equals test for same constant
- class MixEquals(val scrutinee:Symbol, val column:List[Tree], val rest:Rep)(implicit rep:RepFactory) extends RuleApplication(rep) {
+ class MixEquals(val scrutinee: Symbol, val column: List[Tree], val rest: Rep)(implicit rep: RepFactory) extends RuleApplication(rep) {
/** condition (to be used in IF), success and failure Rep */
final def getTransition(implicit theOwner: Symbol): (Tree, Rep, Symbol, Rep) = {
val nmatrix = rest
val vlue = (column.head.tpe: @unchecked) match {
case TypeRef(_,_,List(SingleType(pre,sym))) =>
gen.mkAttributedRef(pre,sym)
+ case TypeRef(_,_,List(PseudoType(o))) =>
+ o.duplicate
}
- assert(vlue.tpe ne null)
+ assert(vlue.tpe ne null, "value tpe is null")
val vs = strip1(column.head)
val nsuccFst = rest.row.head match { case Row(pats,bnd,g,b) => Row(EmptyTree::pats, bnd.add(vs.elements, scrutinee),g,b) }
- //val nsuccRow = nsuccFst :: (column.tail.zip(rest.row.tail) map { case (p, Row(pats,bnd,g,b)) => Row(p::pats,bnd,g,b) })
val fLabel = theOwner.newLabel(scrutinee.pos, cunit.fresh.newName("failCont%")) // warning, untyped
val sx = rep.shortCut(fLabel) // register shortcut
val nsuccRow = nsuccFst :: Row(getDummies( 1 /*scrutinee*/ + rest.temp.length), NoBinding, EmptyTree, sx) :: Nil
-
// todo: optimize if no guard, and no further tests
val nsucc = rep.make(scrutinee :: rest.temp, nsuccRow)
val nfail = repWithoutHead(column,rest)
-
return (typed{ Equals(mkIdent(scrutinee) setType scrutinee.tpe, vlue) }, nsucc, fLabel, nfail)
}
final def tree(implicit theOwner: Symbol, failTree: Tree) = {
val (cond, srep, fLabel, frep) = this.getTransition
- //DBG("MixEquals::tree -- cond "+cond)
val cond2 = typed { rep.handleOuter(cond) }
- //DBG("MixEquals, srep = "+srep)
- //DBG("MixEquals, frep = "+frep)
val fail = typed { repToTree(frep) }
fLabel setInfo (new MethodType(Nil, fail.tpe))
val succ = repToTree(srep)
@@ -696,60 +630,47 @@ trait ParallelMatching {
} catch {
case e =>
Console.println("failed to type-check If")
- Console.println("cond2: "+cond2)
- throw e
+ Console.println("cond2: "+cond2)
+ throw e
}
- } /* def tree(implicit theOwner: Symbol, failTree: Tree) */
- } /* MixEquals */
+ }
+ }
- /**
- * mixture rule for type tests
+ /** mixture rule for type tests
**/
- class MixTypes(val scrutinee:Symbol, val column:List[Tree], val rest:Rep)(implicit rep:RepFactory) extends RuleApplication(rep) {
+ class MixTypes(val scrutinee: Symbol, val column: List[Tree], val rest: Rep)(implicit rep: RepFactory) extends RuleApplication(rep) {
var casted: Symbol = null
- var moreSpecific: List[Tree] = Nil
- var subsumed: List[(Int,List[Tree])] = Nil // row index and subpatterns
- var remaining: List[(Int,Tree)] = Nil // row index and pattern
+ var moreSpecific: List[Tree] = Nil
+ var subsumed: List[(Int,List[Tree])] = Nil // row index and subpatterns
+ var remaining: List[(Int,Tree)] = Nil // row index and pattern
val isExhaustive = !scrutinee.tpe.typeSymbol.hasFlag(symtab.Flags.SEALED) || {
- //DEBUG("check exha for column "+column)
val tpes = column.map {x => x.tpe.typeSymbol}
scrutinee.tpe.typeSymbol.children.forall { sym => tpes.contains(sym) }
}
private val headPatternType = strip2(column.head) match {
- case p @ (_:Ident | _:Select) =>
- singleType(p.symbol.tpe.prefix, p.symbol) //should be singleton object
- //case p@Apply(_,_) if !p.tpe./*?type?*/symbol.hasFlag(symtab.Flags.CASE) => ConstantType(new NamedConstant(p))
- case __UnApply(_,argtpe,_) => argtpe
- case _ => column.head.tpe
+ case p @ (_:Ident | _:Select) => singleType(p.symbol.tpe.prefix, p.symbol) //should be singleton object
+ case __UnApply(_,argtpe,_) => argtpe
+ case _ => column.head.tpe
}
private val isCaseHead = isCaseClass(headPatternType)
- private val dummies = if(!isCaseHead) Nil else getDummies(headPatternType.typeSymbol.caseFieldAccessors.length)
-
- //DBG("headPatternType "+headPatternType)
- //DBG("isCaseHead = "+isCaseHead)
- //DBG("dummies = "+dummies)
+ private val dummies = if (!isCaseHead) Nil else getDummies(headPatternType.typeSymbol.caseFieldAccessors.length)
private def subpatterns(pat:Tree): List[Tree] = {
- //Console.print("subpatterns("+pat+")=")
- //val x =
pat match {
case Bind(_,p) =>
subpatterns(p)
case app @ Apply(fn, pats) if isCaseClass(app.tpe) && (fn.symbol eq null)=>
- if(isCaseHead) pats else dummies
+ if (isCaseHead) pats else dummies
case Apply(fn,xs) => assert((xs.isEmpty) && (fn.symbol ne null), "strange Apply"); dummies // named constant
case _: UnApply =>
dummies
case pat =>
- //Console.println("[class="+pat.getClass()+"]")
dummies
}
- //Console.println(x)
- //x
}
/** returns true if pattern tests an object */
@@ -761,12 +682,8 @@ trait ParallelMatching {
} catch {
case e =>
Console.println("object pattern test throws "+e.getMessage())
- //if(settings_debug)
- // System.exit(-1);
throw e
}
- //Console.println("scrutinee == "+scrutinee+":"+scrutinee.tpe)
- //Console.println("column.head == "+column.head);
/*init block*/ {
var sr = (moreSpecific,subsumed,remaining)
var j = 0; var pats = column; while(pats ne Nil) {
@@ -774,47 +691,29 @@ trait ParallelMatching {
val pat = pats.head
val strippedPattern = strip2(pat)
val patternType = strippedPattern.tpe
- //Console.println("pat = "+pat+" (class "+pat.getClass+")of type "+pat.tpe)
- //Console.println("current pat is wild? = "+isDefaultPattern(pat))
- //Console.println("current pat.symbol = "+pat.symbol+", pat.tpe "+pat.tpe)
- //Console.println("headPatternType = "+headPatternType)
- //Console.println("(current)pat.tpe <:< headPatternType = "+(pat.tpe <:< headPatternType))
- //Console.println("headPatternType <:< (current)pat.tpe = "+(headPatternType <:< pat.tpe))
- //Console.println("(current)pat.tpe =:= headPatternType = "+(pat.tpe <:< headPatternType))
sr = strippedPattern match {
- // case _: Bind => // cannot happen, using strip2
- // case a:Alternative => // cannot happen, alternatives should be preprocessed away
-
case Literal(Constant(null)) if !(headPatternType =:= patternType) => //special case for constant null pattern
- //Console.println("[1")
(ms,ss,(j,pat)::rs);
case _ if objectPattern(pat) =>
- //Console.println("[2")
(EmptyTree::ms, (j,dummies)::ss, rs); // matching an object
case Typed(p, _) if (strip2(p).isInstanceOf[UnApply] && (patternType /*is never <equals>*/ <:< headPatternType)) =>
- //Console.println("unapply arg is same or *more* specific")
(p::ms, (j, dummies)::ss, rs);
case q @ Typed(pp,_) if (patternType_wrtEquals(patternType) <:< headPatternType) =>
- //Console.println("current pattern [Typed] is same or *more* specific")
- ({if(pat.tpe =:= headPatternType /*never true for <equals>*/) pp/*EmptyTree*/ else q}::ms, (j, dummies)::ss, rs);
+ ({if (pat.tpe =:= headPatternType /*never true for <equals>*/) pp else q}::ms, (j, dummies)::ss, rs);
case z:UnApply =>
- //Console.println("current pattern tests something else")
(ms,ss,(j,pat)::rs)
case qq if (patternType_wrtEquals(patternType) <:< headPatternType) && !isDefaultPattern(pat) =>
- //Console.println("current pattern [ ... ] is same or *more* specific")
- ({if(pat.tpe =:= headPatternType /*never true for <equals>*/) EmptyTree else pat}::ms, (j,subpatterns(pat))::ss, rs);
+ ({if (pat.tpe =:= headPatternType /*never true for <equals>*/) EmptyTree else pat}::ms, (j,subpatterns(pat))::ss, rs);
case _ if (headPatternType <:< patternType /*never true for <equals>*/) || isDefaultPattern(pat) =>
- //Console.println("current pattern is *more general*")
- (EmptyTree::ms, (j, dummies)::ss, (j,pat)::rs); // subsuming (matched *and* remaining pattern)
+ (EmptyTree::ms, (j, dummies)::ss, (j,pat)::rs) // subsuming (matched *and* remaining pattern)
case _ =>
- //Console.println("current pattern tests something else")
(ms,ss,(j,pat)::rs)
}
j += 1
@@ -832,25 +731,21 @@ trait ParallelMatching {
/** returns casted symbol, success matrix and optionally fail matrix for type test on the top of this column */
final def getTransition(implicit theOwner: Symbol): (Symbol, Rep, Option[Rep]) = {
- //DBG("*** getTransition! of "+this.toString)
- // the following works for type tests... what fudge is necessary for value comparisons?
- // type test
- casted = if(scrutinee.tpe =:= headPatternType) scrutinee else newVar(scrutinee.pos, headPatternType)
- if(scrutinee.hasFlag(symtab.Flags.TRANS_FLAG))
+ casted = if (scrutinee.tpe =:= headPatternType) scrutinee else newVar(scrutinee.pos, headPatternType)
+ if (scrutinee.hasFlag(symtab.Flags.TRANS_FLAG))
casted.setFlag(symtab.Flags.TRANS_FLAG)
// succeeding => transition to translate(subsumed) (taking into account more specific)
val nmatrix = {
- var ntemps = if(isCaseHead /*for annontated type, isCaseHead == false but isClass(casted.tpe) == true*/) casted.caseFieldAccessors map {
+ var ntemps = if (!isCaseHead) Nil else casted.caseFieldAccessors map {
meth =>
val ctemp = newVar(scrutinee.pos, casted.tpe.memberType(meth).resultType)
- if(scrutinee.hasFlag(symtab.Flags.TRANS_FLAG))
+ if (scrutinee.hasFlag(symtab.Flags.TRANS_FLAG))
ctemp.setFlag(symtab.Flags.TRANS_FLAG)
ctemp
- } else Nil // (***)
+ } // (***) flag needed later
var subtests = subsumed
-
- if(moreSpecific.exists { x => x != EmptyTree }) {
- ntemps = casted::ntemps // (***)
+ if (moreSpecific.exists { x => x != EmptyTree }) {
+ ntemps = casted::ntemps
subtests = moreSpecific.zip(subsumed) map {
case (mspat, (j,pats)) => (j,mspat::pats)
}
@@ -863,85 +758,66 @@ trait ParallelMatching {
val nsubst = osubst.add(vs.elements, casted)
Row(pats ::: opats, nsubst, og, bx)
}
- //DBG("ntemps = "+ntemps.mkString("[["," , ","]]"))
- //DBG("ntriples = "+ntriples.mkString("[[\n","\n, ","\n]]"))
- rep.make(ntemps, ntriples) /*setParent this*/
+ rep.make(ntemps, ntriples)
}
// fails => transition to translate(remaining)
-
val nmatrixFail: Option[Rep] = {
val ntemps = scrutinee :: rest.temp
val ntriples = remaining map {
case (j, pat) => val r = rest.row(j); Row(pat :: r.pat, r.subst, r.guard, r.bx)
}
- if(ntriples.isEmpty) None else Some(rep.make(ntemps, ntriples))
+ if (ntriples.isEmpty) None else Some(rep.make(ntemps, ntriples))
}
- //DBG("nmatrixFail = \n\n"+nmatrixFail)
(casted, nmatrix, nmatrixFail)
- } /* getTransition(implicit theOwner: Symbol): (Symbol, Rep, Option[Rep]) */
+ }
- final def tree(implicit theOwner: Symbol, failTree: Tree) = {
+ final def tree(implicit theOwner: Symbol, failTree: Tree): Tree = {
val (casted,srep,frep) = this.getTransition
val condUntyped = condition(casted.tpe, this.scrutinee)
- var cond = rep.handleOuter(typed { condUntyped }) // <- throws exceptions in some situations?
- if(needsOuterTest(casted.tpe, this.scrutinee.tpe, theOwner)) // @todo merge into def condition
+ var cond = rep.handleOuter(typed { condUntyped })
+ if (needsOuterTest(casted.tpe, this.scrutinee.tpe, theOwner)) // @todo merge into def condition
cond = addOuterCondition(cond, casted.tpe, mkIdent(this.scrutinee), rep.handleOuter)
val succ = repToTree(srep)
- val fail = if(frep.isEmpty) failTree else repToTree(frep.get)
+ val fail = if (frep.isEmpty) failTree else repToTree(frep.get)
// dig out case field accessors that were buried in (***)
- //Console.println("casted:"+casted+": "+casted.tpe)
- val cfa = if(isCaseHead) casted.caseFieldAccessors else Nil
- //Console.println("cfa's:"+cfa.toString)
-
- val caseTemps = (if(!srep.temp.isEmpty && srep.temp.head == casted) srep.temp.tail else srep.temp).zip(cfa)
+ val cfa = if (!isCaseHead) Nil else casted.caseFieldAccessors
+ val caseTemps = (if (!srep.temp.isEmpty && srep.temp.head == casted) srep.temp.tail else srep.temp).zip(cfa)
- //Console.println("case temps"+caseTemps.toString)
try{
- var vdefs = caseTemps map {p =>
- val tmp = p._1; val accessorMethod = p._2
- //Console.println("tmp: "+tmp+":"+tmp.tpe)
- //Console.println("accessorMethod: "+accessorMethod+":"+accessorMethod.tpe)
- val untypedAccess = Apply(Select(mkIdent(casted), accessorMethod),List())
- val typedAccess = typed { untypedAccess }
- //Console.println("ParallelMatching-- MixTypes "+typedAccess)
- typedValDef(tmp, typedAccess)
- }
+ var vdefs = caseTemps map {
+ p =>
+ val tmp = p._1;
+ val accessorMethod = p._2
+ val untypedAccess = Apply(Select(mkIdent(casted), accessorMethod),List())
+ val typedAccess = typed { untypedAccess }
+ typedValDef(tmp, typedAccess)
+ }
- if(casted ne this.scrutinee) {
+ if (casted ne this.scrutinee)
vdefs = ValDef(casted, gen.mkAsInstanceOf(mkIdent(this.scrutinee), casted.tpe)) :: vdefs
- }
- typed { If(cond, squeezedBlock(vdefs,succ), fail) }
+
+ return typed { If(cond, squeezedBlock(vdefs, succ), fail) }
} catch {
case e =>
throw new FatalError("EXCEPTION:"+e.getMessage())
}
- } /* def tree(implicit theOwner: Symbol, failTree: Tree) */
- } /* class MixTypes */
+ }
+ }
/** converts given rep to a tree - performs recursive call to translation in the process to get sub reps
*/
final def repToTree(r: Rep)(implicit theOwner: Symbol, failTree: Tree, rep: RepFactory): Tree = {
r.applyRule.tree
- /*r.applyRule match {
- case r : ErrorRule => Console.println("R1"); r.tree
- case vr: VariableRule => Console.println("R2"); vr.tree
- case mc: MixCases => Console.println("R3"); mc.tree
- case ml: MixLiterals => Console.println("R4"); ml.tree
- case me: MixEquals => Console.println("R5"); me.tree
- case mm: MixTypes => Console.println("R6"); mm.tree
- case mu: MixUnapply => Console.println("R7"); mu.tree
- }*/
}
- /** subst: the bindings so far */
case class Row(pat:List[Tree], subst:Binding, guard:Tree, bx:Int)
object Rep {
type RepType = Product2[List[Symbol], List[Row]]
final def unapply(x:Rep)(implicit rep:RepFactory):Option[RepType] =
- if(x.isInstanceOf[rep.RepImpl]) Some(x.asInstanceOf[RepType]) else None
+ if (x.isInstanceOf[rep.RepImpl]) Some(x.asInstanceOf[RepType]) else None
}
class RepFactory(val handleOuter: Tree => Tree) {
case class RepImpl(val temp:List[Symbol], val row:List[Row]) extends Rep with Rep.RepType {
@@ -963,18 +839,14 @@ trait ParallelMatching {
final def make(temp:List[Symbol], row:List[Row], targets: List[Tree], vss:List[SymList])(implicit theOwner: Symbol): Rep = {
// ensured that labels(i) eq null for all i, cleanup() has to be called after translation
this.targets = targets
- if(targets.length > labels.length)
+ if (targets.length > labels.length)
this.labels = new Array[Symbol](targets.length)
this.vss = vss
- this.reached64 = if(targets.length < 64) new Set64 else null
- //Console.println("targets: "+targets)
- //Console.println("vss: "+vss)
- //Console.print("labels: "); {for(s<-labels) Console.print({if(s ne null) {s} else "_"}+",")}
+ this.reached64 = if (targets.length < 64) new Set64 else null
return make(temp, row)
}
final def shortCut(theLabel:Symbol): Int = {
- //Console.println("adds shortcut:"+theLabel)
this.shortCuts = shortCuts:::theLabel::Nil;
return -shortCuts.length
}
@@ -984,28 +856,17 @@ 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)) {
- /*Console.println("removing labeldef! ")
- Console.println("ld.symbol = "+ld.symbol)
- Console.println("bx = "+bx)
- Console.println("rtwice? "+isReachedTwice(bx))
- Console.println("reached = "+reached) */
+ if ((bx >= 0) && !isReachedTwice(bx)) {
squeezedBlock(vdefs,body)
}
else
blck
- //case If(Literal(Constant(true)), thenp, elsep) =>
- // Console.println("1 short IF affecting "+elsep); thenp
- //case If(Literal(Constant(false)), thenp, elsep) =>
- // Console.println("2 short IF affecting "+thenp); elsep
case If(cond, Literal(Constant(true)), Literal(Constant(false))) =>
super.transform(cond)
case If(cond1, If(cond2, thenp, elsep1), elsep2) if (elsep1 equalsStructure elsep2) =>
- //Console.println("3 short IF affecting "+elsep2);
super.transform(If(And(cond1,cond2), thenp, elsep1))
case If(cond1, If(cond2, thenp, Apply(jmp,List())), ld:LabelDef) if (jmp.symbol eq ld.symbol) =>
- //Console.println("4 short IF affecting "+ld)
super.transform(If(And(cond1,cond2), thenp, ld))
case t => super.transform(t)
@@ -1021,69 +882,56 @@ trait ParallelMatching {
reached = Nil
shortCuts = Nil
}
- final def isReached(bx:Int) = { /*Console.println("isReached("+bx+")"); */labels(bx) ne null }
- final def markReachedTwice(bx:Int) = if(reached64 ne null) { reached64 |= bx } else { reached = insertSorted(bx, reached) }
+ final def isReached(bx:Int) = { labels(bx) ne null }
+ final def markReachedTwice(bx:Int) = if (reached64 ne null) { reached64 |= bx } else { reached = insertSorted(bx, reached) }
/** @pre bx < 0 || labelIndex(bx) != -1 */
- final def isReachedTwice(bx:Int) = (bx < 0) || (if(reached64 ne null) { reached64 contains bx } else { findSorted(bx,reached) })
-
+ final def isReachedTwice(bx:Int) = (bx < 0) || (if (reached64 ne null) { reached64 contains bx } else { findSorted(bx,reached) })
/* @returns bx such that labels(bx) eq label, -1 if no such bx exists */
final def labelIndex(label:Symbol): Int = {
var bx = 0; while((bx < labels.length) && (labels(bx) ne label)) { bx += 1 }
- if(bx >= targets.length) bx = -1
+ if (bx >= targets.length) bx = -1
return bx
}
/** first time bx is requested, a LabelDef is returned. next time, a jump.
* the function takes care of binding
*/
final def requestBody(bx:Int, subst:Binding)(implicit theOwner: Symbol): Tree = {
- if(bx < 0) {// is shortcut
- //Console.println("requestBody ("+bx+") gets shortcut "+(shortCuts.length-bx)+ " all:"+shortCuts);
+ if (bx < 0) {// is shortcut
val jlabel = shortCuts(-bx-1)
- //Console.println("is "+jlabel);
val jump = Apply(mkIdent(jlabel), Nil)
- //Console.println(jump)
- //val jumpT = typed{ jump }
- //Console.println(jumpT)
return jump
}
- //DBG("requestbody("+bx+", "+subst+") isReached(bx)?"+isReached(bx)+" labels:");
- //{for(s<-labels) Console.print({if(s ne null) {s} else "_"}+",")}
- //DBG("vss(bx) = "+vss(bx))
- if(!isReached(bx)) { // first time this bx is requested
+ if (!isReached(bx)) { // first time this bx is requested
val argts = new ListBuffer[Type] // types of
var vrev: List[Symbol] = Nil
var vdefs:List[Tree] = Nil
val it = vss(bx).elements; while(it.hasNext) {
val v = it.next
- //DBG("v = "+v)
val substv = subst(v)
- if(substv ne null) {// might be bound elsewhere ( see `x @ unapply' )
+ if (substv ne null) {// might be bound elsewhere ( see `x @ unapply' )
vrev = v :: vrev
argts += v.tpe
vdefs = typedValDef(v, substv)::vdefs
}
}
val body = targets(bx)
- // bug: typer is not able to digest a body of type Nothing being assigned result type Unit
- val tpe = if(body.tpe.typeSymbol eq definitions.AllClass) body.tpe else resultType
+ // @bug: typer is not able to digest a body of type Nothing being assigned result type Unit
+ val tpe = if (body.tpe.typeSymbol eq definitions.AllClass) body.tpe else resultType
val label = theOwner.newLabel(body.pos, "body%"+bx).setInfo(new MethodType(argts.toList, tpe))
labels(bx) = label
- if(body.isInstanceOf[Throw] || body.isInstanceOf[Literal]) {
+ if (body.isInstanceOf[Throw] || body.isInstanceOf[Literal]) {
return squeezedBlock(vdefs.reverse, body.duplicate setType tpe)
}
- //Console.println("- !isReached returning LabelDef "+label)
- //Console.println("- ! and vdefs "+vdefs)
return squeezedBlock(vdefs, LabelDef(label, vrev.reverse, body setType tpe))
}
- //Console.println("- isReached before, jump to "+labels(bx))
// jump
markReachedTwice(bx) // if some bx is not reached twice, its LabelDef
- val args = new ListBuffer[Ident] // is replaces with body itself
+ val args = new ListBuffer[Ident] // is replaced with body itself
var vs = vss(bx).elements; while(vs.hasNext) {
val substv = subst(vs.next)
- assert(substv ne null) // if sharing takes place, then 'binding elsewhere' is not allowed
+ assert(substv ne null, "subst is null") // if sharing takes place, then 'binding elsewhere' is not allowed
args += substv
}
val label = labels(bx)
@@ -1094,19 +942,19 @@ trait ParallelMatching {
throw FatalError("consistency problem")
}
for((f,a) <- fmls.zip(args.toList)) {
- if(!(a.tpe <:< f)) {
+ if (!(a.tpe <:< f)) {
cunit.error(targets(bx).pos, "consistency problem ! "+a.tpe+" "+f)
throw FatalError("consistency problem")
}
}
}
val body = targets(bx)
- if(body.isInstanceOf[Throw] || body.isInstanceOf[Literal]) {
+ if (body.isInstanceOf[Throw] || body.isInstanceOf[Literal]) {
val vdefs = new ListBuffer[Tree]
val it = vss(bx).elements; while(it.hasNext) {
val v = it.next
val substv = subst(v)
- if(substv ne null) {// might be bound elsewhere ( see `x @ unapply' )
+ if (substv ne null) {// might be bound elsewhere ( see `x @ unapply' )
vdefs += typedValDef(v, substv)
}
}
@@ -1119,7 +967,6 @@ trait ParallelMatching {
/** the injection here handles alternatives and unapply type tests */
final def make(temp:List[Symbol], row1:List[Row])(implicit theOwner: Symbol): Rep = {
- //if(temp.isEmpty && row1.length > 1) return apply(Nil, row1.head::Nil) // small standalone optimization, we won't need other rows (check guard?)
var unchanged: Boolean = true
val row = row1 flatMap {
xx =>
@@ -1147,7 +994,7 @@ trait ParallelMatching {
(strippedPat: @unchecked) match {
case p @ Alternative(ps) =>
- if(indexOfAlternative == -1) {
+ if (indexOfAlternative == -1) {
unchanged = false
indexOfAlternative = j
}
@@ -1164,9 +1011,6 @@ trait ParallelMatching {
if (!o.symbol.isValue) {
singleType(o.tpe.prefix, o.symbol)
} else {
- //DBG("o.tpe "+o.symbol.tpe)
- //DBG("o.tpe "+o.symbol.tpe.isStable)
- //DBG("p.prefix "+o.symbol.tpe.prefix)
singleType(NoPrefix, o.symbol) // equals-check
// call the above `stpe'. Then we could also return
// `typeRef(definitions.ScalaPackageClass.tpe, definitions.EqualsPatternClass, List(stpe))'
@@ -1183,16 +1027,13 @@ trait ParallelMatching {
if (!o.symbol.isValue) {
singleType(o.tpe.prefix, o.symbol)
} else {
- //DBG("stor.tpe "+stor.tpe)
- //DBG("stor.symbol "+stor.symbol)
- //DBG("stor.symbol.tpe "+stor.symbol.tpe)
singleType(NoPrefix, o.symbol) // equals-check
}
val p = Ident(nme.WILDCARD) setType stpe
val q = makeBind(vs,Typed(p, TypeTree(stpe)) setType stpe) setType stpe
pats = q::pats
- case UnApply(Apply(TypeApply(sel @ Select(stor, nme.unapplySeq),List(tptArg)),_),ArrayValue(_,xs)::Nil) if(stor.symbol eq definitions.ListModule) =>
+ case UnApply(Apply(TypeApply(sel @ Select(stor, nme.unapplySeq),List(tptArg)),_),ArrayValue(_,xs)::Nil) if (stor.symbol eq definitions.ListModule) =>
//@pre: is not right-ignoring (no star pattern)
// no exhaustivity check, please
temp(j).setFlag(symtab.Flags.TRANS_FLAG)
@@ -1200,6 +1041,7 @@ trait ParallelMatching {
val nmlzdPat = normalizedListPattern(xs, tptArg.tpe)
pats = makeBind(vs, nmlzdPat) :: pats
+ //@todo: rewrite, using __UnApply instead of UnApply like so:
//case ua @ __UnApply(_,argtpe,_) =>
//val ua = prepat
// val npat = (if (temp(j).tpe <:< argtpe) ua else Typed(ua,TypeTree(argtpe)).setType(argtpe))
@@ -1213,48 +1055,31 @@ trait ParallelMatching {
pats = (makeBind(vs, npat) setType argtpe)::pats
}
- // something too tricky is going on if the outer types don't match
case o @ Apply(fn, List()) if !isCaseClass(o.tpe) =>
- //DBG("o.tpe "+o.tpe)
- //DBG("fn is ")
- //Console.println("o.symbol is a module? "+o.symbol+" "+o.symbol.isModule)
- //Console.println("o.tpe.termSymbol is a module? "+o.tpe.termSymbol+" "+o.tpe.termSymbol.isModule)
val stpe: Type = fn match {
case _ if (o.symbol.isModule) =>
- //DBG("o.symbol is module! "+o.symbol)
- //DBG(nodeToString(fn))
singleType(o.tpe.prefix, o.symbol)
case _ if (o.tpe.termSymbol.isModule) =>
- //Console.println("o.tpe.termSymbol is a module! "+sym)
singleType(o.tpe.prefix, o.symbol)
case Select(path,sym) =>
- //DBG("path "+path);
- //DBG("sym "+sym);
path.tpe match {
case ThisType(sym) =>
singleType(path.tpe, o.symbol)
case _ => // e.g. `case Some(p._2)' in scala.collection.jcl.Map
- singleType(singleType(path.tpe.prefix, path.symbol) , o.symbol) // old
+ if (path.isInstanceOf[Apply])
+ new PseudoType(o) // outer-matching, see test/files/pos/t154.scala
+ else
+ singleType(singleType(path.tpe.prefix, path.symbol), o.symbol) // old
}
- case o @ Ident(_) => // lazy val
- //DBG("sym "+o.symbol)
- //DBG("sym.isValue "+o.symbol.isValue)
- //singleType(NoPrefix, o.symbol) // before
- if (!o.symbol.isValue) {
- singleType(o.tpe.prefix, o.symbol)
- } else {
- singleType(NoPrefix, o.symbol) // equals-check
- }
-
+ case o @ Ident(_) =>
+ if (!o.symbol.isValue)
+ singleType(o.tpe.prefix, o.symbol)
+ else
+ singleType(NoPrefix, o.symbol)
}
- //Console.println("encoding in singleType:"+stpe)
-
val ttst = typeRef(NoPrefix, definitions.EqualsPatternClass, List(stpe))
-
- //Console.println("here's the result: "+ttst)
-
val p = Ident(nme.WILDCARD) setType ttst
val q = makeBind(vs,Typed(p, TypeTree(stpe)) setType ttst)
pats = q::pats
@@ -1264,24 +1089,21 @@ trait ParallelMatching {
val q = makeBind(vs,Typed(EmptyTree, TypeTree(tpe)) setType tpe)
pats = q :: pats
- case Apply_CaseClass_NoArgs(tpe) => // no-args case class pattern
+ case Apply_CaseClass_NoArgs(tpe) => // no-args case class pattern
val q = makeBind(vs, Typed(EmptyTree, TypeTree(tpe)) setType tpe)
pats = q :: pats
- case Apply_CaseClass_WithArgs() => // case class pattern with args
+ case Apply_CaseClass_WithArgs() => // case class pattern with args
pats = opat :: pats
case ArrayValue(_,xs) =>
- //assert(false) // inactive, @see PatternMatchers::isImplemented
pats = opat :: pats
}
- //DBG("!!added "+pats.head+":"+pats.head.tpe)
opats = opats.tail
j += 1
}
pats = pats.reverse
- //i = pats findIndexOf isAlternative
if (indexOfAlternative == -1)
List(Row(pats, subst, g, bx))
else {
@@ -1293,10 +1115,8 @@ trait ParallelMatching {
}
if (unchanged) {
val ri = RepImpl(temp,row).init
- //Console.println("Rep.apply / ri = "+ri)
ri
} else {
- //Console.println("Rep.apply / recursive ")
this.make(temp,row) // recursive call
}
}
@@ -1304,16 +1124,13 @@ trait ParallelMatching {
abstract class Rep {
val temp:List[Symbol]
- val row:List[Row] // (List[Tree], List[(Symbol,Symbol)], Tree, Tree)
-
+ val row:List[Row]
var sealedCols = List[Int]()
var sealedComb = List[Set[Symbol]]()
- //Console.println(" the matrix "+this.toString)
final def init: this.type = {
temp.zipWithIndex.foreach {
case (sym,i) =>
- //Console.println("sym! "+sym+" mutable? "+sym.hasFlag(symtab.Flags.MUTABLE)+" captured? "+sym.hasFlag(symtab.Flags.CAPTURED))
if (sym.hasFlag(symtab.Flags.MUTABLE) && // indicates that have not yet checked exhaustivity
!sym.hasFlag(symtab.Flags.TRANS_FLAG) && // indicates @unchecked
sym.tpe.typeSymbol.hasFlag(symtab.Flags.SEALED)) {
@@ -1322,16 +1139,15 @@ trait ParallelMatching {
sealedCols = i::sealedCols
// this should enumerate all cases... however, also the superclass is taken if it is not abstract
def candidates(tpesym: Symbol): SymSet =
- if(!tpesym.hasFlag(symtab.Flags.SEALED)) emptySymbolSet else
+ if (!tpesym.hasFlag(symtab.Flags.SEALED)) emptySymbolSet else
tpesym.children.flatMap { x =>
val z = candidates(x)
- if(x.hasFlag(symtab.Flags.ABSTRACT)) z else z + x
+ if (x.hasFlag(symtab.Flags.ABSTRACT)) z else z + x
}
val cases = candidates(sym.tpe.typeSymbol)
sealedComb = cases::sealedComb
}
}
-
// computes cartesian product, keeps indices available
def combine(colcom: List[(Int,Set[Symbol])]): List[List[(Int,Symbol)]] = colcom match {
case Nil => Nil
@@ -1339,13 +1155,8 @@ trait ParallelMatching {
case (i,syms)::cs => for (s <- syms.toList; rest <- combine(cs)) yield (i,s) :: rest
}
- if(!sealedCols.isEmpty) {
- //Console.println("cols"+sealedCols)
- //DEBUG("comb")
- //for (com <- sealedComb) //DEBUG(com.toString)
-
+ if (!sealedCols.isEmpty) {
val allcomb = combine(sealedCols zip sealedComb)
- //Console.println("all comb!" + allcomb)
/** returns true if pattern vector pats covers a type symbols "combination"
* @param pats pattern vector
* @param comb pairs of (column index, type symbol)
@@ -1354,25 +1165,21 @@ trait ParallelMatching {
comb forall {
case (i,sym) =>
val p = strip2(pats(i));
- //Console.println("covers? "+p+" "+sym);
val res =
isDefaultPattern(p) || p.isInstanceOf[UnApply] || p.isInstanceOf[ArrayValue] || {
val ptpe = patternType_wrtEquals(p.tpe)
- val symtpe = if(sym.hasFlag(symtab.Flags.MODULE)) {
+ val symtpe = if (sym.hasFlag(symtab.Flags.MODULE)) {
singleType(sym.tpe.prefix, sym.linkedModuleOfClass) // e.g. None, Nil
} else sym.tpe
- //Console.print("covers: sym="+sym+" symtpe="+symtpe+" p="+p+", p.tpe="+p.tpe+" ?")
(ptpe.typeSymbol == sym) || (symtpe <:< ptpe) ||
/* outer, see scala.util.parsing.combinator.lexical.Scanner */
(ptpe.prefix.memberType(sym) <:< ptpe)
}
- //Console.println(res)
res
}
val coversAll = allcomb forall { combination => row exists { r => covers(r.pat, combination)}}
- //Console.println("all combinations covered? "+coversAll)
- if(!coversAll) {
+ if (!coversAll) {
val sb = new StringBuilder()
sb.append("match is not exhaustive!\n")
for (open <- allcomb if !(row exists { r => covers(r.pat, open)})) {
@@ -1390,23 +1197,20 @@ trait ParallelMatching {
cunit.warning(temp.head.pos, sb.toString)
}
}
- //if(settings_debug) Console.println("init done, rep = "+this.toString)
return this
- } /* def init */
-
+ }
/* internal representation is (temp:List[Symbol], row:List[Row])
*
* tmp1 tmp_m
*/
-
final def applyRule(implicit theOwner: Symbol, rep: RepFactory): RuleApplication = row match {
case Nil =>
ErrorRule
case Row(pats, subst, g, bx)::xs =>
var px = 0; var rpats = pats; var bnd = subst; var temps = temp; while((bnd ne null) && (rpats ne Nil)) {
val (vs,p) = strip(rpats.head);
- if(!isDefaultPattern(p)) { /*break*/ bnd = null; } else {
+ if (!isDefaultPattern(p)) { /*break*/ bnd = null; } else {
bnd = bnd.add(vs.elements,temps.head)
rpats = rpats.tail
temps = temps.tail
@@ -1415,24 +1219,21 @@ trait ParallelMatching {
}
/* Row( _ ... _ g_1 b_1 ) :: rows it's all default patterns
*/
- if(bnd ne null) { // all default patterns
- val rest = if(g eq EmptyTree) null else rep.make(temp, xs)
+ if (bnd ne null) { // all default patterns
+ val rest = if (g eq EmptyTree) null else rep.make(temp, xs)
return VariableRule (bnd, g, rest, bx)
}
/* Row( _ ... _ p_1i ... p_1n g_m b_m ) :: rows
*/
-
// cut out column px that contains the non-default pattern
- // assert(px == pats findIndexOf {x => !isDefaultPattern(x)})
val column = rpats.head :: (row.tail map { case Row(pats,_,_,_) => pats(px) })
- // assert(column == row map { case Row(pats,_,_,_) => pats(px) })
val restTemp = temp.take(px) ::: temp.drop(px+1)
val restRows = row map { case Row(pats, subst, g, bx) => Row(pats.take(px) ::: pats.drop(px+1), subst, g, bx) }
return MixtureRule(temps.head, column, rep.make(restTemp,restRows))
- } /* applyRule */
+ }
- // a fancy toString method for debugging
+ // a fancy toString method for debugging
override final def toString = {
val sb = new StringBuilder
val NPAD = 15
@@ -1460,11 +1261,9 @@ trait ParallelMatching {
var cs = cases; while (cs ne Nil) cs.head match { // stash away pvars and bodies for later
case CaseDef(pat,g,b) =>
- //Console.println("pat::"+pat)
- //Console.println("dv ::"+definedVars(pat))
vss += definedVars(pat)
targets += b
- if(roots.length > 1) pat match {
+ if (roots.length > 1) pat match {
case Apply(fn, pargs) =>
row += Row(pargs, NoBinding, g, bx)
case Ident(nme.WILDCARD) =>
@@ -1474,17 +1273,11 @@ trait ParallelMatching {
bx += 1
cs = cs.tail
}
- //Console.println("leaving initRep")
- /*val res = */rep.make(roots, row.toList, targets.toList, vss.toList)
- //Console.println("left initRep")
- //res
+ rep.make(roots, row.toList, targets.toList, vss.toList)
}
-
- // ---------------------------------- helper functions that generate symbols, trees for type tests, pattern tests
-
final def newVar(pos: Position, name: Name, tpe: Type)(implicit theOwner: Symbol): Symbol = {
- if(tpe eq null) assert(tpe ne null, "newVar("+name+", null)")
+ if (tpe eq null) assert(tpe ne null, "newVar("+name+", null)")
val sym = theOwner.newVariable(pos, name) // careful: pos has special meaning
sym setInfo tpe
sym
@@ -1493,14 +1286,9 @@ trait ParallelMatching {
final def newVar(pos: Position, tpe: Type)(implicit theOwner: Symbol): Symbol =
newVar(pos, cunit.fresh.newName("temp"), tpe) setFlag symtab.Flags.SYNTHETIC
- /** returns the condition in "if(cond) k1 else k2"
+ /** returns the condition in "if (cond) k1 else k2"
*/
final def condition(tpe: Type, scrut: Symbol): Tree = {
- val res = condition1(tpe, scrut)
- //DBG("condition, tpe = "+tpe+", scrut.tpe = "+scrut.tpe+", res = "+res)
- res
- }
- final def condition1(tpe: Type, scrut: Symbol): Tree = {
assert(scrut ne NoSymbol)
condition(tpe, mkIdent(scrut))
}
@@ -1508,59 +1296,38 @@ trait ParallelMatching {
final def condition(tpe: Type, scrutineeTree: Tree): Tree = {
assert(tpe ne NoType)
assert(scrutineeTree.tpe ne NoType)
- //Console.println("tpe = "+tpe+" prefix="+tpe.prefix)
- //Console.println("singletontype?"+tpe.isInstanceOf[SingletonType])
- //Console.println("constanttype? "+tpe.isInstanceOf[ConstantType])
if (tpe.isInstanceOf[SingletonType] && !tpe.isInstanceOf[ConstantType]) {
-
if (tpe.termSymbol.isModule) {// object
if (scrutineeTree.tpe <:< definitions.AnyRefClass.tpe)
Eq(gen.mkAttributedRef(tpe.termSymbol), scrutineeTree) // object
else
Equals(gen.mkAttributedRef(tpe.termSymbol), scrutineeTree) // object
} else {
- //Console.print("111 ??")
- //Console.println("tpe.prefix "+tpe.prefix)
- //Console.println("tpe stable "+tpe.isStable)
- //Console.println("tpe prefix stable "+tpe.prefix.isStable)
- //val x = Equals(Apply(gen.mkAttributedRef(tpe./*?term?*/symbol), List()), scrutineeTree)
val x =
- if(tpe.prefix ne NoPrefix) gen.mkIsInstanceOf(scrutineeTree, tpe)
+ if (tpe.prefix ne NoPrefix) gen.mkIsInstanceOf(scrutineeTree, tpe)
else Equals(gen.mkAttributedRef(tpe.termSymbol), scrutineeTree)
- //Console.println(" = "+x)
typed { x }
}
} else if (tpe.isInstanceOf[ConstantType]) {
val value = tpe.asInstanceOf[ConstantType].value
- //if(false && value.isInstanceOf[NamedConstant])
- // Equals(Ident(scrut), value.asInstanceOf[NamedConstant].tree) // constant
- //assert(scrut.tpe <:< definitions.AnyRefClass.tpe, "stupid, should be caught by type checker "+value)
- //else
if (value == Constant(null) && scrutineeTree.tpe <:< definitions.AnyRefClass.tpe)
Eq(scrutineeTree, Literal(value)) // constant
else
Equals(scrutineeTree, Literal(value)) // constant
} else if (scrutineeTree.tpe <:< tpe && tpe <:< definitions.AnyRefClass.tpe) {
- //if(scrutineeTree.symbol.hasFlag(symtab.Flags.SYNTHETIC)) Literal(Constant(true)) else
NotNull(scrutineeTree)
} else
- //Console.println(tpe.prefix.symbol.isTerm)
- //Console.println(tpe./*?type?*/symbol)
- //Console.println(tpe./*?type?*/symbol.linkedModuleOfClass)
gen.mkIsInstanceOf(scrutineeTree, tpe)
}
/** adds a test comparing the dynamic outer to the static outer */
final def addOuterCondition(cond:Tree, tpe2test: Type, scrutinee: Tree, handleOuter: Tree=>Tree) = {
val TypeRef(prefix,_,_) = tpe2test
- //Console.println("addOuterCondition: "+prefix)
assert(prefix ne NoPrefix)
var theRef = prefix match {
case ThisType(clazz) => gen.mkAttributedThis(clazz)
case _ => gen.mkAttributedRef(prefix.prefix, prefix.termSymbol)
}
-
-
// needs explicitouter treatment
theRef = handleOuter(theRef)
@@ -1572,7 +1339,6 @@ trait ParallelMatching {
And(cond,
Eq(Apply(Select(
gen.mkAsInstanceOf(scrutinee, tpe2test, true), outerAcc),List()), theRef))
-
}
}
diff --git a/src/compiler/scala/tools/nsc/matching/TransMatcher.scala b/src/compiler/scala/tools/nsc/matching/TransMatcher.scala
index cc5f3b5505..8c32316e7c 100644
--- a/src/compiler/scala/tools/nsc/matching/TransMatcher.scala
+++ b/src/compiler/scala/tools/nsc/matching/TransMatcher.scala
@@ -1,6 +1,7 @@
/* NSC -- new Scala compiler
* Copyright 2005-2007 LAMP/EPFL
- * @author Burak Emir
+ * Copyright 2007 Google Inc. All Rights Reserved.
+ * Author: bqe@google.com (Burak Emir)
*/
// $Id$
@@ -21,11 +22,8 @@ trait TransMatcher { self: transform.ExplicitOuter with PatternNodes with Parall
import collection.mutable.ListBuffer
var cunit: CompilationUnit = _
-
def fresh = cunit.fresh
-
var nPatterns = 0
-
var resultType: Type = _
// cache these
@@ -39,6 +37,7 @@ trait TransMatcher { self: transform.ExplicitOuter with PatternNodes with Parall
}
return false
}
+
final def isRegularPattern(pat: Tree): Boolean = {
pat match {
case Alternative(trees) => hasRegularPattern(trees)
@@ -55,8 +54,6 @@ trait TransMatcher { self: transform.ExplicitOuter with PatternNodes with Parall
}
}
-
-
// @todo: this should be isNotRegular :-/ premature opt src of all evil
// check special case Seq(p1,...,pk,_*) where pi not regular
protected def isRightIgnoring(p: ArrayValue): Boolean = {
@@ -68,9 +65,9 @@ trait TransMatcher { self: transform.ExplicitOuter with PatternNodes with Parall
p match {
case ArrayValue(s, trees) =>
var ts = trees
- var c: Tree = null
- while ((ts ne Nil) && {c = ts.head; ts = ts.tail; !isRegularPattern(c)}) {}
- (ts eq Nil) && isDefaultStar(c)
+ var c: Tree = null
+ while ((ts ne Nil) && {c = ts.head; ts = ts.tail; !isRegularPattern(c)}) {}
+ (ts eq Nil) && isDefaultStar(c)
}
}
@@ -98,64 +95,31 @@ trait TransMatcher { self: transform.ExplicitOuter with PatternNodes with Parall
pat
case Bind(id, empt @ Sequence(List())) =>
- nilVars = pat.symbol /*id.symbol()*/ :: nilVars
+ nilVars = pat.symbol :: nilVars
empt
case Bind(n, pat1) =>
copy.Bind(pat, n, isRegular1(pat1))
case Sequence(trees) =>
- //isReg = isReg || ( trees.length == 0 );
- isReg = true // cause there are ArrayValues now
+ isReg = true
copy.Sequence(pat, trees map { isRegular1 })
case UnApply(fn, args) => copy.UnApply(pat, fn, args map { isRegular1 })
- /* a pattern of the form List(foo@_*), also called "sequence apply".
- *
- * - last update: discussion with Martin 2005-02-18
- *
- * - tree.fn must be ignored. The analyzer ensures that the selector will be a subtype
- * of fn; it thus assigns the expected type from the context (which is surely a subtype,
- * but may have different flags etc.
- */
- case app @ Apply(fn, List(pat2@ ArrayValue( tt, List(b @ Bind(id, Star(wc @ Ident(nme.WILDCARD))))))) if
- (app.tpe.typeSymbol.flags & Flags.CASE) == 0 =>
- //Console.println("OPTIMIZING")
- //Console.println(pat)
- //Console.println(pat.tpe)
- //Console.println(tt.tpe)
- //Console.println("b.tpe "+b.tpe+" widened"+b.tpe.widen)
- //Console.println("b.symbol.tpe "+b.symbol.tpe+" widened"+b.symbol.tpe.widen)
- //Console.println("pat2.tpe "+pat2.tpe+" widened"+pat2.tpe.widen)
+ case app @ Apply(fn, List(pat2@ ArrayValue( tt, List(b @ Bind(id, Star(wc @ Ident(nme.WILDCARD))))))) if (app.tpe.typeSymbol.flags & Flags.CASE) == 0 =>
val tpe1:Type = pat2.tpe.widen.baseType( definitions.SeqClass ).typeArgs(0)
+ val tpe = appliedType(definitions.SeqClass.typeConstructor, List(tpe1))
+ b.symbol.setInfo(tpe)
+ b.setType(tpe)
+ copy.Bind(b, id, wc)
- val tpe = appliedType(definitions.SeqClass.typeConstructor, List(tpe1))
- b.symbol.setInfo(tpe)
- b.setType(tpe)
- val res = copy.Bind(b, id, wc)
- //Console.println("====>")
- //Console.println(res)
- res
-
- // a pattern of the form MyCaseConstructor(foo@_*)
- case app @ Apply(fn, List(pat2@ ArrayValue( tt, List(b @ Bind(id, Star(wc @ Ident(nme.WILDCARD))))))) =>
- //Console.println("OPTIMIZING")
- //Console.println(pat)
- //Console.println(pat.tpe)
- //Console.println(tt.tpe)
- //Console.println("b.tpe "+b.tpe+" widened"+b.tpe.widen)
- //Console.println("b.symbol.tpe "+b.symbol.tpe+" widened"+b.symbol.tpe.widen)
- //Console.println("pat2.tpe "+pat2.tpe+" widened"+pat2.tpe.widen)
+ case app @ Apply(fn, List(pat2@ ArrayValue( tt, List(b @ Bind(id, Star(wc @ Ident(nme.WILDCARD))))))) => // a pattern of the form MyCaseConstructor(foo@_*)
val tpe1:Type = pat2.tpe.widen.baseType( definitions.SeqClass ).typeArgs(0)
-
- val tpe = appliedType(definitions.SeqClass.typeConstructor, List(tpe1))
- b.symbol.setInfo(tpe)
- b.setType(tpe)
- val res = copy.Apply(pat, fn, List(copy.Bind(b, id, wc)))
- //Console.println("====>")
- //Console.println(res)
- res
+ val tpe = appliedType(definitions.SeqClass.typeConstructor, List(tpe1))
+ b.symbol.setInfo(tpe)
+ b.setType(tpe)
+ copy.Apply(pat, fn, List(copy.Bind(b, id, wc)))
case av @ ArrayValue(s, trees) =>
if (isRightIgnoring(av)) pat
@@ -165,8 +129,6 @@ trait TransMatcher { self: transform.ExplicitOuter with PatternNodes with Parall
pat
case Apply(fn, trees) =>
- //Console.println(" IN isRegular, apply node "+pat.toString());
- //Console.println(" trees are:"+(trees map {x => x.getClass().toString()}));
copy.Apply(pat, fn, (trees map { isRegular1 }))
case Literal(_) =>
@@ -178,14 +140,9 @@ trait TransMatcher { self: transform.ExplicitOuter with PatternNodes with Parall
case Typed(_, _) =>
pat
- case This(_) => // Sean's feature request #1134, compiled incorrectly
+ case This(_) =>
val stpe = mkThisType(pat.tpe.typeSymbol)
Typed(Ident(nme.WILDCARD) setType stpe, TypeTree(stpe))
-
- //case _ =>
- // Console.println(pat);
- // Console.println(pat.getClass());
- // scala.Predef.error(" what is this ? ")
}
var res = new ListBuffer[CaseDef]
@@ -208,92 +165,83 @@ trait TransMatcher { self: transform.ExplicitOuter with PatternNodes with Parall
}
/** handles all translation of pattern matching
- */
- def handlePattern(selector: Tree, ocases: List[CaseDef], doCheckExhaustive: Boolean,
- owner: Symbol, handleOuter: Tree => Tree): Tree = {
- // TEMPORARY
- //new NewMatcher().toIR(sel, ocases)
- //
- // 1. is there a regular pattern?
-
- val (cases, containsReg) = isRegular(ocases)
-
- // @todo: remove unused variables
-
- if (containsReg) {
- cunit.error(selector.pos, "regular expressions not yet implemented")
- //sel
- EmptyTree
- } else {
- implicit val theOwner = owner
- if (settings_debug) {
- Console.println("****")
- Console.println("**** initalize, selector = "+selector+" selector.tpe = "+selector.tpe)
- Console.println("**** doCheckExhaustive == "+doCheckExhaustive)
- }
+ */
+ def handlePattern(selector: Tree, ocases: List[CaseDef], doCheckExhaustive: Boolean, owner: Symbol, handleOuter: Tree => Tree): Tree = {
+ val (cases, containsReg) = isRegular(ocases)
+ // @todo: remove unused variables
+ if (containsReg) {
+ cunit.error(selector.pos, "regular expressions not yet implemented")
+ //sel
+ EmptyTree
+ } else {
+ implicit val theOwner = owner
+ if (settings_debug) {
+ Console.println("****")
+ Console.println("**** initalize, selector = "+selector+" selector.tpe = "+selector.tpe)
+ Console.println("**** doCheckExhaustive == "+doCheckExhaustive)
+ }
- implicit val rep = new RepFactory(handleOuter)
- try {
-
- val tmps = new ListBuffer[Symbol]
- val vds = new ListBuffer[Tree]
- var root:Symbol = newVar(selector.pos, selector.tpe)
- if (!doCheckExhaustive)
- root.setFlag(symtab.Flags.TRANS_FLAG)
-
- var vdef:Tree = typed{ValDef(root, selector)}
- var theFailTree:Tree = ThrowMatchError(selector.pos, mkIdent(root))
-
- if(definitions.isTupleType(selector.tpe)) selector match {
- case app @ Apply(fn, args)
- if (fn.symbol eq selector.tpe.decls.lookup(nme.CONSTRUCTOR)) &&
- (cases forall { x => x match {
- case CaseDef(Apply(fn, pargs),_,_) => true ;
- case CaseDef(Ident(nme.WILDCARD),_,_) => true ;
- case _ => false
- }}) =>
- var i = 0
- var as = args
- while(as ne Nil) {
- val ti = as.head
- val v = newVar(ti.pos, cunit.fresh.newName("tp"), selector.tpe.typeArgs(i))
- if (!doCheckExhaustive)
- v.setFlag(symtab.Flags.TRANS_FLAG)
- vds += typedValDef(v, ti)
- tmps += v
- i = i + 1
- as = as.tail
- }
- theFailTree = ThrowMatchError(selector.pos, copy.Apply(app, fn, tmps.toList map mkIdent))
- case _ =>
- tmps += root
- vds += vdef
- } else {
+ implicit val rep = new RepFactory(handleOuter)
+ try {
+ val tmps = new ListBuffer[Symbol]
+ val vds = new ListBuffer[Tree]
+ var root:Symbol = newVar(selector.pos, selector.tpe)
+ if (!doCheckExhaustive)
+ root.setFlag(symtab.Flags.TRANS_FLAG)
+
+ var vdef:Tree = typed{ValDef(root, selector)}
+ var theFailTree:Tree = ThrowMatchError(selector.pos, mkIdent(root))
+
+ if (definitions.isTupleType(selector.tpe)) selector match {
+ case app @ Apply(fn, args)
+ if (fn.symbol eq selector.tpe.decls.lookup(nme.CONSTRUCTOR)) &&
+ (cases forall { x => x match {
+ case CaseDef(Apply(fn, pargs),_,_) => true ;
+ case CaseDef(Ident(nme.WILDCARD),_,_) => true ;
+ case _ => false
+ }}) =>
+ var i = 0
+ var as = args
+ while(as ne Nil) {
+ val ti = as.head
+ val v = newVar(ti.pos, cunit.fresh.newName("tp"), selector.tpe.typeArgs(i))
+ if (!doCheckExhaustive)
+ v.setFlag(symtab.Flags.TRANS_FLAG)
+ vds += typedValDef(v, ti)
+ tmps += v
+ i = i + 1
+ as = as.tail
+ }
+ theFailTree = ThrowMatchError(selector.pos, copy.Apply(app, fn, tmps.toList map mkIdent))
+ case _ =>
tmps += root
vds += vdef
- }
- val irep = initRep(tmps.toList, cases, rep)
+ } else {
+ tmps += root
+ vds += vdef
+ }
+ val irep = initRep(tmps.toList, cases, rep)
- implicit val fail: Tree = theFailTree
+ implicit val fail: Tree = theFailTree
- val mch = typed{ repToTree(irep)}
- var dfatree = typed{squeezedBlock(vds.toList, mch)}
+ val mch = typed{ repToTree(irep)}
+ var dfatree = typed{squeezedBlock(vds.toList, mch)}
- //DEBUG("**** finished\n"+dfatree.toString)
- var bx = 0; var cs = cases; while(cs ne Nil) {
- if(!rep.isReached(bx)) {
- cunit.error(cs.head.asInstanceOf[CaseDef].body.pos, "unreachable code")
- }
- cs = cs.tail
- bx += 1
+ //DEBUG("**** finished\n"+dfatree.toString)
+ var bx = 0; var cs = cases; while(cs ne Nil) {
+ if (!rep.isReached(bx)) {
+ cunit.error(cs.head.asInstanceOf[CaseDef].body.pos, "unreachable code")
}
- dfatree = rep.cleanup(dfatree)
- resetTrav.traverse(dfatree)
- return dfatree
- } catch {
- case e => e.printStackTrace(); throw new FatalError(e.getMessage())
+ cs = cs.tail
+ bx += 1
}
+ dfatree = rep.cleanup(dfatree)
+ resetTrav.traverse(dfatree)
+ return dfatree
+ } catch {
+ case e => e.printStackTrace(); throw new FatalError(e.getMessage())
}
+ }
}
object resetTrav extends Traverser {
@@ -307,5 +255,4 @@ trait TransMatcher { self: transform.ExplicitOuter with PatternNodes with Parall
super.traverse(x)
}
}
-
}