summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler/scala/tools/nsc/matching/ParallelMatching.scala115
-rw-r--r--src/compiler/scala/tools/nsc/matching/PatternMatchers.scala13
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Definitions.scala11
-rw-r--r--src/compiler/scala/tools/nsc/symtab/StdNames.scala1
-rw-r--r--test/files/run/patmatnew.scala14
-rw-r--r--test/files/run/unboxmatch.check2
-rw-r--r--test/files/run/unboxmatch.scala10
7 files changed, 134 insertions, 32 deletions
diff --git a/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala b/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala
index 013db5fbf2..4d3e984266 100644
--- a/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala
+++ b/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala
@@ -32,6 +32,12 @@ trait ParallelMatching {
case _ => false
}
+ def isEqualsPattern(tpe: Type) =
+ tpe match {
+ case TypeRef(_, sym, _) => sym eq definitions.EqualsPatternClass
+ case _ => false
+ }
+
// ---------------------------------- data
sealed trait RuleApplication {
@@ -111,6 +117,11 @@ trait ParallelMatching {
Console.println(")///")
}
*/
+ if(isEqualsPattern(column.head.tpe)) {
+ if(settings_debug) { Console.println("\n%%% MixEquals") }
+ return new MixEquals(scrutinee, column, rest)
+ }
+
if(isSimpleIntSwitch) {
if(settings_debug) { Console.println("\n%%% MixLiterals") }
return new MixLiterals(scrutinee, column, rest)
@@ -405,6 +416,28 @@ trait ParallelMatching {
}
}
+ class MixEquals(val scrutinee:Symbol, val column:List[Tree], val rest:Rep) extends RuleApplication {
+ final def getTransition(implicit theOwner: Symbol): (Tree, Rep, Rep) = {
+ val nmatrix = rest
+ val vlue = column.head.tpe match {
+ case TypeRef(_,_,List(SingleType(pre,sym))) =>
+ gen.mkAttributedRef(pre,sym)
+ }
+ var fcol = column.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)
+ }
+ fcol = fcol.tail
+ frow = frow.tail
+ }
+ val nfail = Rep(scrutinee::rest.temp, nfailrow.toList)
+ return (typed{ Equals(Ident(scrutinee) setType scrutinee.tpe, vlue) }, rest, nfail)
+ }
+ }
/**
* mixture rule for type tests
**/
@@ -711,6 +744,29 @@ trait ParallelMatching {
Match(selector, cases ::: defCase :: Nil)
}
+ case me:MixEquals =>
+ val (cond,srep,frep) = me.getTransition
+ val cond2 = try{
+ typed { handleOuter(cond) }
+ } catch {
+ case e =>
+ Console.println("failed to type-check cond2")
+ Console.println("cond: "+cond)
+ Console.println("cond2: "+handleOuter(cond))
+ throw e
+ }
+
+ val succ = repToTree(srep, handleOuter)
+ val fail = repToTree(frep, handleOuter)
+ try {
+ typed{ If(cond2, succ, fail) }
+ } catch {
+ case e =>
+ Console.println("failed to type-check If")
+ Console.println("cond2: "+cond2)
+ throw e
+ }
+
case mm:MixTypes =>
val (casted,srep,frep) = mm.getTransition
//Console.println("--- mixture \n succ \n"+srep.toString+"\n fail\n"+frep.toString)
@@ -840,12 +896,17 @@ object Rep {
}
}
val body = targets(bx)
- val label = theOwner.newLabel(body.pos, "body%"+bx).setInfo(new MethodType(argts.toList, body.tpe/*resultType*/))
+ val label = theOwner.newLabel(body.pos, "body%"+bx).setInfo(new MethodType(argts.toList, resultType/*body.tpe*/))
//Console.println("label.tpe"+label.tpe)
+
labels(bx) = label
+
+ if(body.isInstanceOf[Throw]) {
+ return squeezedBlock(vdefs.reverse, body.duplicate setType resultType)
+ }
//Console.println("- !isReached returning LabelDef "+label)
//Console.println("- ! and vdefs "+vdefs)
- return Block(vdefs, LabelDef(label, vrev.reverse, body))
+ return Block(vdefs, LabelDef(label, vrev.reverse, body setType resultType))
}
//Console.println("- isReached before, jump to "+labels(bx))
@@ -871,6 +932,19 @@ object Rep {
}
}
}
+ if(targets(bx).isInstanceOf[Throw]) {
+ 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' )
+ vdefs += typedValDef(v, substv)
+ }
+ }
+ return squeezedBlock(vdefs.toList, targets(bx).duplicate setType resultType)
+ }
+
+
return Apply(Ident(label),args.toList)
}
@@ -960,22 +1034,31 @@ object Rep {
/** something too tricky is going on if the outer types don't match
*/
- case o @ Apply(app, List()) if !isCaseClass(o.tpe) =>
- System.out.println("this should not happen (experimental code)")
- throw new RuntimeException("non-case apply encountered in parallelmatching")
- //Console.println(o)
- //val stpe = singleType(NoPrefix, o.symbol)
- val stpe =
- if (o.tpe.termSymbol.isModule) singleType(o.tpe.prefix, o.symbol)
- else {
- singleType(NoPrefix, o.symbol) // equals-check
- }
- val p = Ident(nme.WILDCARD) setType stpe
- val q = Typed(p, TypeTree(stpe)) setType stpe
+ case o @ Apply(fn, List()) if !isCaseClass(o.tpe) =>
+ val stpe = fn match {
+ case Select(path,sym) =>
+ if (o.tpe.termSymbol.isModule) singleType(o.tpe.prefix, o.symbol)
+ else path.tpe match {
+ case ThisType(sym) =>
+ singleType(path.tpe, o.symbol)
+ case _ =>
+ singleType(singleType(path.tpe.prefix, path.symbol), o.symbol)
+ }
+ case Ident(_) => // lazy val
+ singleType(NoPrefix, o.symbol)
+ }
+ //Console.println("encoding in singleType:"+stpe)
+
+ val ttst = typeRef(definitions.ScalaPackageClass.tpe, definitions.EqualsPatternClass, List(stpe))
+
+ //Console.println("here's the result: "+ttst)
+
+ val p = Ident(nme.WILDCARD) setType ttst
+ val q = Typed(p, TypeTree(stpe)) setType ttst
pats = q::pats
- case o @ Apply(app, Nil) => // no args case class pattern
- assert(isCaseClass(o.tpe))
+ case o @ Apply(fn, Nil) => // no args case class pattern
+ assert(isCaseClass(o.tpe), o.toString)
val q = Typed(EmptyTree, TypeTree(o.tpe)) setType o.tpe
pats = q :: pats
diff --git a/src/compiler/scala/tools/nsc/matching/PatternMatchers.scala b/src/compiler/scala/tools/nsc/matching/PatternMatchers.scala
index ed9e1c7b68..dee4b32bfe 100644
--- a/src/compiler/scala/tools/nsc/matching/PatternMatchers.scala
+++ b/src/compiler/scala/tools/nsc/matching/PatternMatchers.scala
@@ -249,9 +249,16 @@ trait PatternMatchers { self: transform.ExplicitOuter with PatternNodes with Par
//Console.println("isImplemented? "+x)
x match {
case app @ Apply(fn,xs) =>
- if(!isCaseClass(app.tpe) /*|| (fn.symbol ne null)*/)
- CantHandleApply
- else {
+ if(!isCaseClass(app.tpe)) { /*|| (fn.symbol ne null)*/
+ //Console.println(app)
+ //Console.println(app.tpe)
+ //Console.println(app.symbol)
+ //Console.println(fn.symbol)
+ if(!xs.isEmpty) {
+ return CantHandleApply // System.exit(-1); // this should never happen
+ }
+ null
+ } else {
/*if(!app.tpe.symbol.hasFlag(symtab.Flags.CASE)) {
Console.print("what is this?"+x)
if(fn.symbol eq null) {
diff --git a/src/compiler/scala/tools/nsc/symtab/Definitions.scala b/src/compiler/scala/tools/nsc/symtab/Definitions.scala
index 5ae53ef3d8..5ea6d14648 100644
--- a/src/compiler/scala/tools/nsc/symtab/Definitions.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Definitions.scala
@@ -136,6 +136,8 @@ trait Definitions {
//var UnsealedClass: Symbol = _
lazy val UncheckedClass: Symbol = getClass("scala.unchecked")
+ var EqualsPatternClass: Symbol = _
+
val MaxTupleArity = 22
val TupleClass: Array[Symbol] = new Array(MaxTupleArity + 1)
def tupleField(n: Int, j: Int) = getMember(TupleClass(n), "_" + j)
@@ -763,6 +765,15 @@ trait Definitions {
ByNameParamClass = newCovariantPolyClass(
ScalaPackageClass, nme.BYNAME_PARAM_CLASS_NAME, tparam => AnyClass.typeConstructor)
+ EqualsPatternClass = newClass(ScalaPackageClass, nme.EQUALS_PATTERN_NAME, List());
+ {
+ val tparam = newTypeParam(EqualsPatternClass, 0);
+ EqualsPatternClass.setInfo(
+ PolyType(
+ List(tparam),
+ ClassInfoType(List(AnyClass.typeConstructor), newScope, EqualsPatternClass)))
+ }
+
/* <unapply> */
//UnsealedClass = getClass("scala.unsealed") //todo: remove once 2.4 is out.
diff --git a/src/compiler/scala/tools/nsc/symtab/StdNames.scala b/src/compiler/scala/tools/nsc/symtab/StdNames.scala
index 7ca5d64b02..c2e70528fc 100644
--- a/src/compiler/scala/tools/nsc/symtab/StdNames.scala
+++ b/src/compiler/scala/tools/nsc/symtab/StdNames.scala
@@ -176,6 +176,7 @@ trait StdNames {
val ROOTPKG = newTermName("_root_")
val REPEATED_PARAM_CLASS_NAME = newTermName("<repeated>")
val BYNAME_PARAM_CLASS_NAME = newTermName("<byname>")
+ val EQUALS_PATTERN_NAME = newTermName("<equals>")
val SELF = newTermName("$this")
val CONSTRUCTOR = newTermName("<init>")
diff --git a/test/files/run/patmatnew.scala b/test/files/run/patmatnew.scala
index d9e36a35fe..a54bac814f 100644
--- a/test/files/run/patmatnew.scala
+++ b/test/files/run/patmatnew.scala
@@ -31,7 +31,8 @@ object Test extends TestConsoleMain {
new TestStream,
new Test903,
new Test1093,
- new Test1163_Order
+ new Test1163_Order,
+ new TestUnbox
)
class Foo(j:Int) {
@@ -133,6 +134,17 @@ object Test extends TestConsoleMain {
def runTest() = assertEquals("both", (Var("x"),Var("y")), f)
}
+ class TestUnbox extends TestCase("unbox") {
+ override def runTest() {
+ val xyz: (int, String, boolean) = (1, "abc", true)
+ xyz._1 match {
+ case 1 => "OK"
+ case 2 => assert(false); "KO"
+ case 3 => assert(false); "KO"
+ }
+ }
+ }
+
class Test806_818 { // #806, #811 compile only -- type of bind
// bug811
trait Core {
diff --git a/test/files/run/unboxmatch.check b/test/files/run/unboxmatch.check
deleted file mode 100644
index e14f671011..0000000000
--- a/test/files/run/unboxmatch.check
+++ /dev/null
@@ -1,2 +0,0 @@
-(1,abc,true)
-OK
diff --git a/test/files/run/unboxmatch.scala b/test/files/run/unboxmatch.scala
deleted file mode 100644
index e354798ebd..0000000000
--- a/test/files/run/unboxmatch.scala
+++ /dev/null
@@ -1,10 +0,0 @@
-object Test extends Application {
- var xyz: (int, String, boolean) = _
- xyz = (1, "abc", true)
- Console.println(xyz)
- xyz._1 match {
- case 1 => Console.println("OK")
- case 2 => Console.println("KO")
- case 3 => Console.println("KO")
- }
-}