From 3cebbd7ceafac3a653a74f3b22af37e3683566c7 Mon Sep 17 00:00:00 2001 From: Burak Emir Date: Mon, 13 Aug 2007 14:27:47 +0000 Subject: Definitions, Par: encoding equality patterns us... Definitions, Par: encoding equality patterns using pattern type code generation: if pattern body is throw, generate throw directly (no sharing) tests:moved unboxmatch into patmatnew --- .../tools/nsc/matching/ParallelMatching.scala | 115 ++++++++++++++++++--- .../scala/tools/nsc/matching/PatternMatchers.scala | 13 ++- .../scala/tools/nsc/symtab/Definitions.scala | 11 ++ src/compiler/scala/tools/nsc/symtab/StdNames.scala | 1 + test/files/run/patmatnew.scala | 14 ++- test/files/run/unboxmatch.check | 2 - test/files/run/unboxmatch.scala | 10 -- 7 files changed, 134 insertions(+), 32 deletions(-) delete mode 100644 test/files/run/unboxmatch.check delete mode 100644 test/files/run/unboxmatch.scala 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))) + } + /* */ //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("") val BYNAME_PARAM_CLASS_NAME = newTermName("") + val EQUALS_PATTERN_NAME = newTermName("") val SELF = newTermName("$this") val CONSTRUCTOR = newTermName("") 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") - } -} -- cgit v1.2.3