summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBurak Emir <emir@epfl.ch>2007-08-23 22:41:27 +0000
committerBurak Emir <emir@epfl.ch>2007-08-23 22:41:27 +0000
commite07c5695f30c8e56a1fb389a8a1dab8fb7240ee9 (patch)
tree1f89a21bb2e5818bf5d2d40933821f03f3d24750
parent7440758377e246ece693ca05c3e426bba6135f88 (diff)
downloadscala-e07c5695f30c8e56a1fb389a8a1dab8fb7240ee9.tar.gz
scala-e07c5695f30c8e56a1fb389a8a1dab8fb7240ee9.tar.bz2
scala-e07c5695f30c8e56a1fb389a8a1dab8fb7240ee9.zip
all guards are pulled out into DefDefs, new pat...
all guards are pulled out into DefDefs, new pattern matcher handles guards now.
-rw-r--r--src/compiler/scala/tools/nsc/matching/ParallelMatching.scala99
-rw-r--r--src/compiler/scala/tools/nsc/matching/PatternMatchers.scala31
-rw-r--r--src/compiler/scala/tools/nsc/matching/PatternNodes.scala8
-rw-r--r--src/compiler/scala/tools/nsc/matching/TransMatcher.scala4
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Symbols.scala3
-rw-r--r--src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala42
6 files changed, 100 insertions, 87 deletions
diff --git a/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala b/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala
index 8cee476a37..89e856f08d 100644
--- a/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala
+++ b/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala
@@ -135,44 +135,27 @@ trait ParallelMatching {
}
/** translate outcome of the rule application into code (possible involving recursive application of rewriting) */
- def tree(implicit handleOuter: HandleOuter, localTyper: LocalTyper, theOwner: Symbol, failTree: Tree): Tree
+ def tree(implicit theOwner: Symbol, failTree: Tree): Tree
}
case class ErrorRule(implicit rep:RepFactory) extends RuleApplication(rep) {
def scrutinee:Symbol = throw new RuntimeException("this never happens")
- final def tree(implicit handleOuter: HandleOuter, localTyper: LocalTyper, theOwner: Symbol, failTree: Tree) = failTree
+ final def tree(implicit theOwner: Symbol, failTree: Tree) = failTree
}
/** {case ... if guard => bx} else {guardedRest} */
case class VariableRule(subst:Binding, guard: Tree, guardedRest:Rep, bx: Int)(implicit rep:RepFactory) extends RuleApplication(rep) {
def scrutinee:Symbol = throw new RuntimeException("this never happens")
- final def tree(implicit handleOuter: HandleOuter, localTyper: LocalTyper, theOwner: Symbol, failTree: Tree): Tree = {
+ final def tree(implicit theOwner: Symbol, failTree: Tree): Tree = {
val body = typed { rep.requestBody(bx, subst) }
if(guard eq EmptyTree)
return body
- //Console.println("guard in variable rule"+guard)
val vdefs = targetParams(subst)
- val typedElse = repToTree(guardedRest, handleOuter,localTyper)
-
- // crucial: use local typer, it has the the context needed to enter new class symbols
- val otyper = localTyper//typer.atOwner(theOwner)
- val resetGuard = resetAttrs(guard.duplicate)
- val typedGuard0 = atPhase(phase.prev) {otyper.typed{ resetGuard }}
- val typedGuard = handleOuter(typedGuard0)
- val typedIf = typed{If(typedGuard, body, typedElse)}
-
- val r = try {
- typer.typed { squeezedBlock(vdefs, typedIf) }/*} */
- } catch {
- case e => e.printStackTrace();
- throw new FatalError(e.getMessage());
- null
- }
- //Console.println("genBody-guard PRE:"+r)
- //val r2 = handleOuter(r)
- //Console.println("genBody-guard POST:"+r2)
- r
- } /* def tree(implicit handleOuter: HandleOuter, theOwner: Symbol, failTree: Tree) */
+ val typedElse = repToTree(guardedRest)
+ val typedIf = typed{If(guard.duplicate, body, typedElse)}
+
+ typer.typed { squeezedBlock(vdefs, typedIf) }
+ } /* def tree(implicit theOwner: Symbol, failTree: Tree) */
}
@@ -275,11 +258,11 @@ trait ParallelMatching {
Row(column(tagIndexPairs.index)::pats, nbindings, g, bx)
}
- final def tree(implicit handleOuter: HandleOuter, localTyper: LocalTyper, theOwner: Symbol, failTree: Tree): Tree = {
+ 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, handleOuter,localTyper)
+ var ndefault = if(default.isEmpty) failTree else repToTree(default.get)
var cases = branches map {
case (tag, r) =>
CaseDef(Literal(tag),
@@ -292,9 +275,9 @@ trait ParallelMatching {
val vtmp = newVar(pat.pos, ptpe)
squeezedBlock(
List(typedValDef(vtmp, gen.mkAsInstanceOf(mkIdent(this.scrutinee), ptpe))),
- repToTree(rep.make(vtmp :: r.temp.tail, r.row),handleOuter,localTyper)
+ repToTree(rep.make(vtmp :: r.temp.tail, r.row))
)
- } else repToTree(r, handleOuter,localTyper)
+ } else repToTree(r)
}
)}
@@ -313,7 +296,7 @@ trait ParallelMatching {
case _ => val defCase = CaseDef(mk_(definitions.IntClass.tpe), EmptyTree, ndefault)
Match(Select(mkIdent(this.scrutinee),nme.tag), cases ::: defCase :: Nil)
}
- } /* def tree(implicit handleOuter: HandleOuter, theOwner: Symbol, failTree: Tree) */
+ } /* def tree(implicit theOwner: Symbol, failTree: Tree) */
} /* MixCases */
/**
@@ -383,11 +366,11 @@ trait ParallelMatching {
}
}/*end block*/
- final def tree(implicit handleOuter: HandleOuter, localTyper: LocalTyper, theOwner: Symbol, failTree: Tree): Tree = {
+ 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, rep) => CaseDef(Literal(tag), EmptyTree, repToTree(rep, handleOuter,localTyper)) }
- var ndefault = if(defaultRepOpt.isEmpty) failTree else repToTree(defaultRepOpt.get, handleOuter,localTyper)
+ val cases = branches map { case (tag, rep) => CaseDef(Literal(tag), EmptyTree, repToTree(rep)) }
+ var ndefault = if(defaultRepOpt.isEmpty) failTree else repToTree(defaultRepOpt.get)
renamingBind(defaultV, this.scrutinee, ndefault) // each v in defaultV gets bound to scrutinee
if(cases.length == 1) {
@@ -409,7 +392,7 @@ trait ParallelMatching {
}
return Match(mkIdent(this.scrutinee), cases ::: defCase :: Nil)
}
- } /* def tree(implicit handleOuter: HandleOuter, theOwner: Symbol, failTree: Tree) */
+ } /* def tree(implicit theOwner: Symbol, failTree: Tree) */
} /* MixLiterals */
/**
@@ -501,18 +484,18 @@ trait ParallelMatching {
}}
} /* def getTransition(...) */
- final def tree(implicit handleOuter: HandleOuter, localTyper: LocalTyper, theOwner: Symbol, failTree: Tree) = {
+ final def tree(implicit theOwner: Symbol, failTree: Tree) = {
val (uacall/*:ValDef*/ , vdefs,srep,frep) = this.getTransition // uacall is a Valdef
//Console.println("getTransition"+(uacall,vdefs,srep,frep))
- val succ = repToTree(srep, handleOuter,localTyper)
- val fail = if(frep.isEmpty) failTree else repToTree(frep.get, handleOuter,localTyper)
+ val succ = repToTree(srep)
+ val fail = if(frep.isEmpty) failTree else repToTree(frep.get)
val cond =
if(uacall.symbol.tpe.typeSymbol eq definitions.BooleanClass)
typed{ mkIdent(uacall.symbol) }
else
emptynessCheck(uacall.symbol)
- typed { squeezedBlock(List(handleOuter(uacall)), If(cond,squeezedBlock(vdefs,succ),fail)) }
- } /* def tree(implicit handleOuter: HandleOuter, theOwner: Symbol, failTree: Tree) */
+ 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
@@ -578,10 +561,10 @@ trait ParallelMatching {
}
}
- final def tree(implicit handleOuter: HandleOuter, theOwner: Symbol, failTree: Tree) = {
+ final def tree(implicit theOwner: Symbol, failTree: Tree) = {
val (cx,srep,frep) = this.getTransition
- val succ = repToTree(srep, handleOuter)
- val fail = repToTree(frep, handleOuter)
+ val succ = repToTree(srep)
+ val fail = repToTree(frep)
cx(succ)(fail)
}
@@ -604,21 +587,21 @@ trait ParallelMatching {
return (typed{ Equals(mkIdent(scrutinee) setType scrutinee.tpe, vlue) }, nsucc, nfail)
}
- final def tree(implicit handleOuter: HandleOuter, localTyper: LocalTyper, theOwner: Symbol, failTree: Tree) = {
+ final def tree(implicit theOwner: Symbol, failTree: Tree) = {
val (cond,srep,frep) = this.getTransition
//Console.println("MixEquals::tree -- cond "+cond)
val cond2 = try{
- typed { handleOuter(cond) }
+ typed { rep.handleOuter(cond) }
} catch {
case e =>
Console.println("failed to type-check cond2")
Console.println("cond: "+cond)
- Console.println("cond2: "+handleOuter(cond))
+ Console.println("cond2: "+rep.handleOuter(cond))
throw e
}
- val succ = repToTree(srep, handleOuter,localTyper)
- val fail = repToTree(frep, handleOuter,localTyper)
+ val succ = repToTree(srep)
+ val fail = repToTree(frep)
try {
typed{ If(cond2, succ, fail) }
} catch {
@@ -627,7 +610,7 @@ trait ParallelMatching {
Console.println("cond2: "+cond2)
throw e
}
- } /* def tree(implicit handleOuter: HandleOuter, theOwner: Symbol, failTree: Tree) */
+ } /* def tree(implicit theOwner: Symbol, failTree: Tree) */
} /* MixEquals */
/**
@@ -801,15 +784,15 @@ trait ParallelMatching {
(casted, nmatrix, nmatrixFail)
} /* getTransition(implicit theOwner: Symbol): (Symbol, Rep, Option[Rep]) */
- final def tree(implicit handleOuter: HandleOuter, localTyper: LocalTyper, theOwner: Symbol, failTree: Tree) = {
+ final def tree(implicit theOwner: Symbol, failTree: Tree) = {
val (casted,srep,frep) = this.getTransition
val condUntyped = condition(casted.tpe, this.scrutinee)
- var cond = handleOuter(typed { condUntyped }) // <- throws exceptions in some situations?
+ var cond = rep.handleOuter(typed { condUntyped }) // <- throws exceptions in some situations?
if(needsOuterTest(casted.tpe, this.scrutinee.tpe)) // @todo merge into def condition
- cond = addOuterCondition(cond, casted.tpe, mkIdent(this.scrutinee), handleOuter)
- val succ = repToTree(srep, handleOuter, localTyper)
+ cond = addOuterCondition(cond, casted.tpe, mkIdent(this.scrutinee), rep.handleOuter)
+ val succ = repToTree(srep)
- val fail = if(frep.isEmpty) failTree else repToTree(frep.get, handleOuter,localTyper)
+ 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)
@@ -838,14 +821,12 @@ trait ParallelMatching {
case e =>
throw new FatalError("EXCEPTION:"+e.getMessage())
}
- } /* def tree(implicit handleOuter: HandleOuter, theOwner: Symbol, failTree: Tree) */
+ } /* 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, handleOuter: HandleOuter, localTyper: LocalTyper)(implicit theOwner: Symbol, failTree: Tree, rep: RepFactory): Tree = {
- implicit val HandleOuter = handleOuter
- implicit val LocalTyper = localTyper
+ final def repToTree(r: Rep)(implicit theOwner: Symbol, failTree: Tree, rep: RepFactory): Tree = {
r.applyRule.tree
/*
rep.applyRule match {
@@ -875,7 +856,7 @@ trait ParallelMatching {
final def unapply(x:Rep)(implicit rep:RepFactory):Option[RepType] =
if(x.isInstanceOf[rep.RepImpl]) Some(x.asInstanceOf[RepType]) else None
}
- class RepFactory {
+ class RepFactory(val handleOuter: Tree => Tree) {
case class RepImpl(val temp:List[Symbol], val row:List[Row]) extends Rep with Rep.RepType {
(row.find { case Row(pats, _, _, _) => temp.length != pats.length }) match {
case Some(row) => assert(false, "temp == "+temp+" row.pats == "+row.pat);
@@ -1496,7 +1477,7 @@ trait ParallelMatching {
}
/** adds a test comparing the dynamic outer to the static outer */
- final def addOuterCondition(cond:Tree, tpe2test: Type, scrutinee: Tree, handleOuter: HandleOuter) = {
+ final def addOuterCondition(cond:Tree, tpe2test: Type, scrutinee: Tree, handleOuter: Tree=>Tree) = {
val TypeRef(prefix,_,_) = tpe2test
//Console.println("addOuterCondition: "+prefix)
assert(prefix ne NoPrefix)
diff --git a/src/compiler/scala/tools/nsc/matching/PatternMatchers.scala b/src/compiler/scala/tools/nsc/matching/PatternMatchers.scala
index 9e1e14cf89..1dd6541f9f 100644
--- a/src/compiler/scala/tools/nsc/matching/PatternMatchers.scala
+++ b/src/compiler/scala/tools/nsc/matching/PatternMatchers.scala
@@ -53,16 +53,13 @@ trait PatternMatchers { self: transform.ExplicitOuter with PatternNodes with Par
import global.{ definitions => defs }
- var handleOuter: HandleOuter = _
+ var handleOuter: Tree => Tree = _
- var localTyper: LocalTyper = _
-
- def initialize(selector: Tree, doCheckExhaustive: Boolean, owner: Symbol, _handleOuter:Tree=>Tree, _localTyper:Tree=>Tree): Unit = {
+ def initialize(selector: Tree, doCheckExhaustive: Boolean, owner: Symbol, _handleOuter:Tree=>Tree ): Unit = {
this.owner = owner
this.doCheckExhaustive = doCheckExhaustive
this.selector = selector
- this.handleOuter = new HandleOuter( _handleOuter )
- this.localTyper = new LocalTyper( _localTyper )
+ this.handleOuter = _handleOuter
if (settings_debug) {
Console.println("****")
Console.println("**** initalize, selector = "+selector+" selector.tpe = "+selector.tpe)
@@ -184,7 +181,7 @@ trait PatternMatchers { self: transform.ExplicitOuter with PatternNodes with Par
cases1 = cases1.tail
}
- implicit val rep = new RepFactory()
+ implicit val rep = new RepFactory(handleOuter)
try {
val irep = initRep(selector, cases, doCheckExhaustive, rep)
val root = irep.temp.head
@@ -192,7 +189,7 @@ trait PatternMatchers { self: transform.ExplicitOuter with PatternNodes with Par
implicit val fail: Tree = ThrowMatchError(selector.pos, mkIdent(root))
val vdef = typed{ValDef(root, selector)}
- val mch = typed{repToTree(irep, handleOuter, localTyper)}
+ val mch = typed{repToTree(irep)}
dfatree = typed{squeezedBlock(List(vdef), mch)}
//DEBUG("**** finished\n"+dfatree.toString)
@@ -267,7 +264,7 @@ trait PatternMatchers { self: transform.ExplicitOuter with PatternNodes with Par
} else {
isImplemented(xs, guard)
}
- case p @ Ident(n) => if(guard eq EmptyTree) null else CantHandleGuard
+ case p @ Ident(n) => null //if(guard eq EmptyTree) null else CantHandleGuard
//case UnApply(fn,xs) => isImplemented(xs, guard)
case UnApply(fn,xs) =>
@@ -275,7 +272,7 @@ trait PatternMatchers { self: transform.ExplicitOuter with PatternNodes with Par
// List.unapply<...>(xs)
case Apply(TypeApply(sel @ Select(stor, nme.unapplySeq),_),_) if(stor.symbol eq definitions.ListModule) =>
(xs: @unchecked) match {
- case ArrayValue(_,ys)::Nil => return {if(guard eq EmptyTree) isImplemented(ys, guard) else CantHandleGuard }
+ case ArrayValue(_,ys)::Nil => isImplemented(ys, guard) // return {if(guard eq EmptyTree) isImplemented(ys, guard) else CantHandleGuard }
}
// ignore other unapplySeq occurrences, since will run into ArrayValue
@@ -286,8 +283,8 @@ trait PatternMatchers { self: transform.ExplicitOuter with PatternNodes with Par
case Bind(n, p) => isImplemented(p , guard)
case Alternative(xs) => isImplemented(xs, guard)
case p:Literal => null
- case p:Select => if(guard eq EmptyTree) null else CantHandleGuard
- case p:Typed => if(guard eq EmptyTree) null else CantHandleGuard
+ case p:Select => null // if(guard eq EmptyTree) null else CantHandleGuard
+ case p:Typed => null // if(guard eq EmptyTree) null else CantHandleGuard
// ArrayValue nodes can also appear in repeated parameter positions of case classes (e.g. xml.Elem)
case ArrayValue(_,xs) => CantHandleSeq
@@ -947,13 +944,12 @@ print()
*/
private def generalSwitchToTree(): Tree = {
this.exit = owner.newLabel(root.pos, "exit").setInfo(new MethodType(List(resultType), resultType));
- //val result = exit.newValueParameter(root.pos, "result").setInfo( resultType );
val result = owner.newVariable(root.pos, "result").setInfo( resultType );
squeezedBlock(
List(
typedValDef(root.casted, selector),
- typedValDef(result, EmptyTree /* defaultValue(result.tpe) */),
- typed { toTree(root.and) },
+ typedValDef(result, EmptyTree),
+ typed { toTree(root.and) },
ThrowMatchError(selector.pos, mkIdent(root.casted))) ,
LabelDef(exit, List(result), mkIdent(result)))
}
@@ -1014,8 +1010,9 @@ print()
Literal(Constant(true))
); // forward jump
- if (guard(i) != EmptyTree)
- res0 = And(handleOuter(guard(i)), res0);
+ if (guard(i) != EmptyTree) { // no need for handleout
+ res0 = And(guard(i), res0);
+ }
res = Or(squeezedBlock(ts.toList, res0), res)
i = i - 1
}
diff --git a/src/compiler/scala/tools/nsc/matching/PatternNodes.scala b/src/compiler/scala/tools/nsc/matching/PatternNodes.scala
index d87a197642..44b1d96f42 100644
--- a/src/compiler/scala/tools/nsc/matching/PatternNodes.scala
+++ b/src/compiler/scala/tools/nsc/matching/PatternNodes.scala
@@ -37,8 +37,13 @@ trait PatternNodes { self: transform.ExplicitOuter =>
case n => EmptyTree::getDummies(i-1)
}
+ def makeBind(vs:SymList, pat:Tree): Tree =
+ if(vs eq Nil) pat else Bind(vs.head, makeBind(vs.tail, pat)) setType pat.tpe
+
def normalizedListPattern(pats:List[Tree], tptArg:Type): Tree = pats match {
case Nil => gen.mkAttributedRef(definitions.NilModule)
+ case sp::xs if strip2(sp).isInstanceOf[Star] =>
+ makeBind(definedVars(sp), Ident(nme.WILDCARD) setType sp.tpe)
case x::xs =>
var resType: Type = null;
val consType: Type = definitions.ConsClass.primaryConstructor.tpe match {
@@ -173,9 +178,6 @@ trait PatternNodes { self: transform.ExplicitOuter =>
case _ => false
}
- final case class HandleOuter(transform:Tree=>Tree) { def apply(x:Tree) = transform(x) }
- final case class LocalTyper(typed:Tree=>Tree) { def apply(x:Tree) = typed(x) }
-
/** pvar: the symbol of the pattern variable
* temp: the temp variable that holds the actual value
* next: next binding
diff --git a/src/compiler/scala/tools/nsc/matching/TransMatcher.scala b/src/compiler/scala/tools/nsc/matching/TransMatcher.scala
index e2e57ccbc2..29c156a537 100644
--- a/src/compiler/scala/tools/nsc/matching/TransMatcher.scala
+++ b/src/compiler/scala/tools/nsc/matching/TransMatcher.scala
@@ -223,7 +223,7 @@ trait TransMatcher { self: transform.ExplicitOuter with PatternNodes with CodeFa
/** handles all translation of pattern matching
*/
def handlePattern(sel: Tree, ocases: List[CaseDef], doCheckExhaustive: Boolean,
- owner: Symbol, handleOuter: Tree => Tree, localTyper: Tree => Tree): Tree = {
+ owner: Symbol, handleOuter: Tree => Tree): Tree = {
// TEMPORARY
//new NewMatcher().toIR(sel, ocases)
//
@@ -239,7 +239,7 @@ trait TransMatcher { self: transform.ExplicitOuter with PatternNodes with CodeFa
EmptyTree
} else {
val pm = new PatternMatcher()
- pm.initialize(sel, doCheckExhaustive, owner,handleOuter, localTyper)
+ pm.initialize(sel, doCheckExhaustive, owner, handleOuter)
pm.construct(cases)
//if (global.log()) {
// global.log("internal pattern matching structure");
diff --git a/src/compiler/scala/tools/nsc/symtab/Symbols.scala b/src/compiler/scala/tools/nsc/symtab/Symbols.scala
index 857c178057..d39329aab2 100644
--- a/src/compiler/scala/tools/nsc/symtab/Symbols.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Symbols.scala
@@ -1334,7 +1334,8 @@ trait Symbols {
override def name: Name =
if (phase.flatClasses && rawowner != NoSymbol && !rawowner.isPackageClass) {
if (flatname == nme.EMPTY) {
- //assert(rawowner.isClass) //bqe: this assert prevents duplication of classdefs (e.g Interpreter.scala)
+ if(!rawowner.isClass) { Console.print("warning, is not a class, actually: "+rawowner.name.toString)}
+ //assert(rawowner.isClass) //bq: assert here shadows more important messages
flatname = newTypeName(rawowner.name.toString() + "$" + rawname)
}
flatname
diff --git a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala
index 4aeb4c2cbb..11cc801d71 100644
--- a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala
+++ b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala
@@ -389,7 +389,7 @@ abstract class ExplicitOuter extends InfoTransform with TransMatcher with Patter
}
super.transform(copy.Apply(tree, sel, outerVal :: args))
- case Match(selector, cases) => // <----- transmatch hook
+ case mch @ Match(selector, cases) => // <----- transmatch hook
val tid = if (settings.debug.value) {
val q = unit.fresh.newName("tidmark")
Console.println("transforming patmat with tidmark "+q+" ncases = "+cases.length)
@@ -412,8 +412,39 @@ abstract class ExplicitOuter extends InfoTransform with TransMatcher with Patter
var nselector = transform(selector)
//assert(nselector.tpe =:= selector.tpe)
//val ncases = transformCaseDefs(cases)
- val ncases = cases map {
- case CaseDef(p,g,b) => CaseDef(transform(p),g,transform(b))
+
+ def makeGuardDef(vs:SymList, guard:Tree) = {
+ import symtab.Flags._
+ val gdname = cunit.fresh.newName("gd")
+ val fmls = new ListBuffer[Type]
+ val method = currentOwner.newMethod(mch.pos, gdname) setFlag (SYNTHETIC)
+ var vs1 = vs; while (vs1 ne Nil) {
+ fmls += vs1.head.tpe
+ vs1 = vs1.tail
+ }
+ val tpe = new MethodType(fmls.toList, definitions.BooleanClass.tpe)
+ method setInfo tpe
+ localTyper.
+ typed { DefDef(method,
+ {vparamss =>
+ new ChangeOwnerTraverser(currentOwner, method).traverse(guard);
+ new TreeSymSubstituter(vs, vparamss.head).traverse(guard);guard})}
+ }
+
+ val nguard = new ListBuffer[Tree]
+ val ncases = new ListBuffer[CaseDef]
+ var cs = cases; while (cs ne Nil) {
+ cs.head match {
+ case CaseDef(p,EmptyTree,b) =>
+ ncases += CaseDef(transform(p), EmptyTree, transform(b))
+ case CaseDef(p, guard, b) =>
+ val vs = definedVars(p)
+ val guardDef = makeGuardDef(vs, guard)
+ nguard += transform(guardDef)
+ val gdcall = localTyper.typed{Apply(Ident(guardDef.symbol),vs.map {Ident(_)})}
+ ncases += CaseDef(transform(p), gdcall, transform(b))
+ }
+ cs = cs.tail
}
var checkExhaustive = true
@@ -435,7 +466,7 @@ abstract class ExplicitOuter extends InfoTransform with TransMatcher with Patter
//Console.println("TransMatcher selector.tpe ="+selector.tpe+")")
//Console.println("TransMatcher resultType ="+resultType+")")
- val t_untyped = handlePattern(nselector, ncases, checkExhaustive, currentOwner, transform, {x:Tree => localTyper.typed(x)})
+ val t_untyped = handlePattern(nselector, ncases.toList, checkExhaustive, currentOwner, transform)
try {
//Console.println("t_untyped "+t_untyped.toString())
val t = atPos(tree.pos) { localTyper.typed(t_untyped, resultType) }
@@ -446,7 +477,8 @@ abstract class ExplicitOuter extends InfoTransform with TransMatcher with Patter
//Console.println("t typed "+t.toString())
if (settings.debug.value)
Console.println("finished translation of " + tid)
- t
+
+ if(nguard.isEmpty) {t} else Block(nguard.toList, t) setType t.tpe
} catch {
case e =>
e.printStackTrace()