diff options
author | Paul Phillips <paulp@improving.org> | 2010-10-06 22:56:56 +0000 |
---|---|---|
committer | Paul Phillips <paulp@improving.org> | 2010-10-06 22:56:56 +0000 |
commit | cd92aad821eb476f68ea85fb9b149ee185a08e97 (patch) | |
tree | d88eb6f15428090f075d7da71ea32e90ceb7cc19 | |
parent | b8c07db737b55a2ce34190b17013215dc13940ae (diff) | |
download | scala-cd92aad821eb476f68ea85fb9b149ee185a08e97.tar.gz scala-cd92aad821eb476f68ea85fb9b149ee185a08e97.tar.bz2 scala-cd92aad821eb476f68ea85fb9b149ee185a08e97.zip |
Unreverting r23174. No review.
20 files changed, 138 insertions, 124 deletions
diff --git a/src/compiler/scala/tools/ant/Scalac.scala b/src/compiler/scala/tools/ant/Scalac.scala index 6cda588419..20ed9fc6d4 100644 --- a/src/compiler/scala/tools/ant/Scalac.scala +++ b/src/compiler/scala/tools/ant/Scalac.scala @@ -91,7 +91,7 @@ class Scalac extends MatchingTask with ScalacShared { /** Defines valid values for properties that refer to compiler phases. */ object CompilerPhase extends PermissibleValue { val values = List("namer", "typer", "pickler", "uncurry", "tailcalls", - "transmatch", "explicitouter", "erasure", "lambdalift", + "explicitouter", "erasure", "lambdalift", "flatten", "constructors", "mixin", "icode", "jvm", "terminal") } diff --git a/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala b/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala index e0c1453c3a..55e9ec0b89 100644 --- a/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala +++ b/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala @@ -520,7 +520,7 @@ class ModelFactory(val global: Global, val settings: doc.Settings) { thisFactory case tp: TypeRef if (tp.typeSymbol == definitions.ByNameParamClass) => nameBuffer append "⇒ " appendType0(tp.args.head) - case tp: TypeRef if (definitions.isTupleType(tp)) => + case tp: TypeRef if (definitions.isTupleTypeOrSubtype(tp)) => nameBuffer append '(' appendTypes0(tp.args, ", ") nameBuffer append ')' diff --git a/src/compiler/scala/tools/nsc/interpreter/CompletionOutput.scala b/src/compiler/scala/tools/nsc/interpreter/CompletionOutput.scala index 9b9d9a36f1..e0d678b961 100644 --- a/src/compiler/scala/tools/nsc/interpreter/CompletionOutput.scala +++ b/src/compiler/scala/tools/nsc/interpreter/CompletionOutput.scala @@ -15,7 +15,7 @@ trait CompletionOutput { self: Completion => import global._ - import definitions.{ NothingClass, AnyClass, isTupleType, isFunctionType, isRepeatedParamType } + import definitions.{ NothingClass, AnyClass, isTupleTypeOrSubtype, isFunctionType, isRepeatedParamType } /** Reducing fully qualified noise for some common packages. */ @@ -49,7 +49,7 @@ trait CompletionOutput { def typeToString(tp: Type): String = relativize( tp match { case x if isFunctionType(x) => functionString(x) - case x if isTupleType(x) => tupleString(x) + case x if isTupleTypeOrSubtype(x) => tupleString(x) case x if isRepeatedParamType(x) => typeToString(x.typeArgs.head) + "*" case mt @ MethodType(_, _) => methodTypeToString(mt) case x => x.toString diff --git a/src/compiler/scala/tools/nsc/matching/Matrix.scala b/src/compiler/scala/tools/nsc/matching/Matrix.scala index 0bd9caf506..fa3e7371a7 100644 --- a/src/compiler/scala/tools/nsc/matching/Matrix.scala +++ b/src/compiler/scala/tools/nsc/matching/Matrix.scala @@ -76,7 +76,36 @@ trait Matrix extends MatrixAdditions { states. Otherwise,the error state is used after its reference count has been incremented. **/ + /** Handles all translation of pattern matching. + */ + def handlePattern( + selector: Tree, // tree being matched upon (called scrutinee after this) + cases: List[CaseDef], // list of cases in the match + isChecked: Boolean, // whether exhaustiveness checking is enabled (disabled with @unchecked) + context: MatrixContext): Tree = + { + import context._ + log("handlePattern: selector.tpe = " + selector.tpe) + + // sets up top level match + val matrixInit: MatrixInit = { + val v = copyVar(selector, isChecked, selector.tpe, "temp") + MatrixInit(List(v), cases, atPos(selector.pos)(MATCHERROR(v.ident))) + } + + val matrix = new MatchMatrix(context) { lazy val data = matrixInit } + val rep = matrix.expansion // expands casedefs and assigns name + val mch = typer typed rep.toTree // executes algorithm, converts tree to DFA + val dfatree = typer typed Block(matrixInit.valDefs, mch) // packages into a code block + + // redundancy check + matrix.targets filter (_.isNotReached) foreach (cs => cunit.error(cs.body.pos, "unreachable code")) + // optimize performs squeezing and resets any remaining TRANS_FLAGs + tracing("handlePattern(" + selector + ")", matrix optimize dfatree) + } + case class MatrixContext( + cunit: CompilationUnit, // current unit handleOuter: Tree => Tree, // for outer pointer typer: Typer, // a local typer owner: Symbol, // the current owner @@ -164,7 +193,8 @@ trait Matrix extends MatrixAdditions { override def toString() = "%s: %s = %s".format(lhs, lhs.info, rhs) } - // val NoPatternVar = PatternVar(NoSymbol, EmptyTree, false) + + def newName(pos: Position, s: String) = cunit.fresh.newName(pos, s) /** Sets the rhs to EmptyTree, which makes the valDef ignored in Scrutinee. */ diff --git a/src/compiler/scala/tools/nsc/matching/MatrixAdditions.scala b/src/compiler/scala/tools/nsc/matching/MatrixAdditions.scala index b880dea858..55613c5bd7 100644 --- a/src/compiler/scala/tools/nsc/matching/MatrixAdditions.scala +++ b/src/compiler/scala/tools/nsc/matching/MatrixAdditions.scala @@ -28,6 +28,8 @@ trait MatrixAdditions extends ast.TreeDSL private[matching] trait Squeezer { self: MatrixContext => + private val settings_squeeze = settings.Xsqueeze.value == "on" + def squeezedBlockPVs(pvs: List[PatternVar], exp: Tree): Tree = squeezedBlock(pvs map (_.valDef), exp) diff --git a/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala b/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala index 3606bda6e0..61a8b81820 100644 --- a/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala +++ b/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala @@ -547,7 +547,7 @@ trait ParallelMatching extends ast.TreeDSL owner.newLabel(scrut.pos, newName(scrut.pos, "failCont%")) setInfo MethodType(Nil, labelBody.tpe) lazy val cond = - handleOuter(scrut.id MEMBER_== rhs) + handleOuter(rhs MEMBER_== scrut.id ) lazy val success = remake(List( rest.rows.head.insert2(List(NoPattern), head.boundVariables, scrut.sym), diff --git a/src/compiler/scala/tools/nsc/matching/Patterns.scala b/src/compiler/scala/tools/nsc/matching/Patterns.scala index a135655b9d..26ad296614 100644 --- a/src/compiler/scala/tools/nsc/matching/Patterns.scala +++ b/src/compiler/scala/tools/nsc/matching/Patterns.scala @@ -348,7 +348,7 @@ trait Patterns extends ast.TreeDSL { def apply(x: Apply): Pattern = { val Apply(fn, args) = x def isModule = x.symbol.isModule || x.tpe.termSymbol.isModule - def isTuple = isTupleType(fn.tpe) + def isTuple = isTupleTypeOrSubtype(fn.tpe) if (fn.isType) { if (isTuple) TuplePattern(x) diff --git a/src/compiler/scala/tools/nsc/matching/TransMatcher.scala b/src/compiler/scala/tools/nsc/matching/TransMatcher.scala deleted file mode 100644 index be455b00b0..0000000000 --- a/src/compiler/scala/tools/nsc/matching/TransMatcher.scala +++ /dev/null @@ -1,91 +0,0 @@ -/* NSC -- new Scala compiler - * Copyright 2005-2010 LAMP/EPFL - * Copyright 2007 Google Inc. All Rights Reserved. - * Author: bqe@google.com (Burak Emir) - */ - -package scala.tools.nsc -package matching - -import symtab.SymbolTable -import transform.ExplicitOuter -import java.io.{ StringWriter, PrintWriter } -import scala.reflect.NameTransformer.decode -import PartialFunction._ - -/** Translation of pattern matching - * - * @author Burak Emir - */ -trait TransMatcher extends ast.TreeDSL { - self: ExplicitOuter with ParallelMatching => - - import global.{ typer => _, _ } - import analyzer.Typer - import definitions._ - import CODE._ - import Debug.{ TRACE, tracing } - - // cunit is set to the current unit in ExplicitOuter's transformUnit, - // and nulled out afterward to avoid leaking. - var cunit: CompilationUnit = _ - - def newName(pos: Position, s: String) = cunit.fresh.newName(pos, s) - - final val settings_squeeze = settings.Xsqueeze.value == "on" - - /** Handles all translation of pattern matching. - */ - def handlePattern( - selector: Tree, // tree being matched upon (called scrutinee after this) - cases: List[CaseDef], // list of cases in the match - isChecked: Boolean, // whether exhaustiveness checking is enabled (disabled with @unchecked) - context: MatrixContext): Tree = - { - import context._ - - def matchError(obj: Tree) = atPos(selector.pos)(MATCHERROR(obj)) - def caseIsOk(c: CaseDef) = cond(c.pat) { case _: Apply | Ident(nme.WILDCARD) => true } - def rootTypes = selector.tpe.typeArgs - - // this appears to be an attempt at optimizing when all case defs are constructor - // patterns, but I don't think it's correct. - def doApply(fn: Tree): Boolean = - (fn.symbol eq (selector.tpe.decls lookup nme.CONSTRUCTOR)) && - (cases forall caseIsOk) - - // For x match { ... we start with a single root - def singleMatch(): MatrixInit = { - val v = copyVar(selector, isChecked) - context.MatrixInit(List(v), cases, matchError(v.ident)) - } - - // For (x, y, z) match { ... we start with multiple roots, called tpXX. - def tupleMatch(app: Apply): MatrixInit = { - val Apply(fn, args) = app - val vs = args zip rootTypes map { case (arg, tpe) => copyVar(arg, isChecked, tpe, "tp") } - def merror = matchError(treeCopy.Apply(app, fn, vs map (_.ident))) - - context.MatrixInit(vs, cases, merror) - } - - // sets up top level variables and algorithm input - val matrixInit = tracing("matrixInit", selector match { - case app @ Apply(fn, _) if isTupleType(selector.tpe) && doApply(fn) => tupleMatch(app) - case _ => singleMatch() - }) - - val matrix = new MatchMatrix(context) { lazy val data = matrixInit } - val rep = matrix.expansion // expands casedefs and assigns name - val mch = typer typed rep.toTree // executes algorithm, converts tree to DFA - val dfatree = typer typed Block(matrixInit.valDefs, mch) // packages into a code block - - // redundancy check - matrix.targets filter (_.isNotReached) foreach (cs => cunit.error(cs.body.pos, "unreachable code")) - // optimize performs squeezing and resets any remaining TRANS_FLAGs - val res = matrix optimize dfatree - TRACE("handlePattern(%s, ...) = %s", selector, res) - res - } -} - diff --git a/src/compiler/scala/tools/nsc/symtab/Definitions.scala b/src/compiler/scala/tools/nsc/symtab/Definitions.scala index 77f5cbebbb..99e7979e0b 100644 --- a/src/compiler/scala/tools/nsc/symtab/Definitions.scala +++ b/src/compiler/scala/tools/nsc/symtab/Definitions.scala @@ -288,9 +288,15 @@ trait Definitions extends reflect.generic.StandardDefinitions { lazy val AbstractFunctionClass = mkArityArray("runtime.AbstractFunction", MaxFunctionArity, 0) def tupleField(n: Int, j: Int) = getMember(TupleClass(n), "_" + j) - def isTupleType(tp: Type): Boolean = cond(tp.normalize) { - case TypeRef(_, sym, elems) => elems.length <= MaxTupleArity && sym == TupleClass(elems.length) + def isTupleType(tp: Type): Boolean = isTupleType(tp, false) + def isTupleTypeOrSubtype(tp: Type): Boolean = isTupleType(tp, true) + private def isTupleType(tp: Type, subtypeOK: Boolean): Boolean = cond(tp.normalize) { + case t @ TypeRef(_, sym, elems) => + elems.length <= MaxTupleArity && + (sym == TupleClass(elems.length) || + subtypeOK && !tp.isHigherKinded && (t <:< TupleClass(elems.length).tpe)) } + def tupleType(elems: List[Type]) = if (elems.length <= MaxTupleArity) { val sym = TupleClass(elems.length) diff --git a/src/compiler/scala/tools/nsc/symtab/Types.scala b/src/compiler/scala/tools/nsc/symtab/Types.scala index 2535a38eb3..21da19c526 100644 --- a/src/compiler/scala/tools/nsc/symtab/Types.scala +++ b/src/compiler/scala/tools/nsc/symtab/Types.scala @@ -1852,7 +1852,7 @@ A type's typeSymbol should never be inspected directly. return "=> " + args(0).toString if (isFunctionType(this)) return normalize.typeArgs.init.mkString("(", ", ", ")") + " => " + normalize.typeArgs.last - if (isTupleType(this)) + if (isTupleTypeOrSubtype(this)) return normalize.typeArgs.mkString("(", ", ", if (normalize.typeArgs.length == 1) ",)" else ")") if (sym.isAliasType && (prefixChain exists (_.termSymbol hasFlag SYNTHETIC))) { val normed = normalize; diff --git a/src/compiler/scala/tools/nsc/transform/CleanUp.scala b/src/compiler/scala/tools/nsc/transform/CleanUp.scala index 0739deec5f..932b05c250 100644 --- a/src/compiler/scala/tools/nsc/transform/CleanUp.scala +++ b/src/compiler/scala/tools/nsc/transform/CleanUp.scala @@ -47,9 +47,6 @@ abstract class CleanUp extends Transform with ast.TreeDSL { private def typedWithPos(pos: Position)(tree: Tree) = localTyper typed { atPos(pos)(tree) } - override def transformUnit(unit: CompilationUnit) = - unit.body = transform(unit.body) - /** A value class is defined to be only Java-compatible values: unit is * not part of it, as opposed to isValueClass in definitions. scala.Int is * a value class, java.lang.Integer is not. */ diff --git a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala index c4251ffeea..1403377367 100644 --- a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala +++ b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala @@ -9,7 +9,7 @@ package transform import symtab._ import Flags.{ CASE => _, _ } import scala.collection.mutable.ListBuffer -import matching.{ TransMatcher, Patterns, ParallelMatching } +import matching.{ Patterns, ParallelMatching } /** This class ... * @@ -17,7 +17,6 @@ import matching.{ TransMatcher, Patterns, ParallelMatching } * @version 1.0 */ abstract class ExplicitOuter extends InfoTransform - with TransMatcher with Patterns with ParallelMatching with TypingTransformers @@ -357,7 +356,7 @@ abstract class ExplicitOuter extends InfoTransform var nselector = transform(selector) def makeGuardDef(vs: List[Symbol], guard: Tree) = { - val gdname = newName(guard.pos, "gd") + val gdname = unit.fresh.newName(guard.pos, "gd") val method = currentOwner.newMethod(tree.pos, gdname) setFlag SYNTHETIC val fmls = vs map (_.tpe) val tpe = new MethodType(method newSyntheticValueParams fmls, BooleanClass.tpe) @@ -400,7 +399,7 @@ abstract class ExplicitOuter extends InfoTransform } val t = atPos(tree.pos) { - val context = MatrixContext(transform, localTyper, currentOwner, tree.tpe) + val context = MatrixContext(currentRun.currentUnit, transform, localTyper, currentOwner, tree.tpe) val t_untyped = handlePattern(nselector, ncases, checkExhaustive, context) /* if @switch annotation is present, verify the resulting tree is a Match */ @@ -488,7 +487,7 @@ abstract class ExplicitOuter extends InfoTransform }) super.transform(treeCopy.Apply(tree, sel, outerVal :: args)) - // TransMatch hook + // entry point for pattern matcher translation case mch: Match => matchTranslation(mch) @@ -508,9 +507,7 @@ abstract class ExplicitOuter extends InfoTransform /** The transformation method for whole compilation units */ override def transformUnit(unit: CompilationUnit) { - cunit = unit atPhase(phase.next) { super.transformUnit(unit) } - cunit = null } } diff --git a/src/compiler/scala/tools/nsc/transform/UnCurry.scala b/src/compiler/scala/tools/nsc/transform/UnCurry.scala index b7a70bdf4b..7ca0f089f1 100644 --- a/src/compiler/scala/tools/nsc/transform/UnCurry.scala +++ b/src/compiler/scala/tools/nsc/transform/UnCurry.scala @@ -158,7 +158,7 @@ abstract class UnCurry extends InfoTransform with TypingTransformers { override def transformUnit(unit: CompilationUnit) { freeMutableVars.clear freeLocalsTraverser(unit.body) - unit.body = transform(unit.body) + super.transformUnit(unit) } private var nprinted = 0 diff --git a/src/library/scala/reflect/generic/Trees.scala b/src/library/scala/reflect/generic/Trees.scala index c880a335de..87ce15dd24 100755 --- a/src/library/scala/reflect/generic/Trees.scala +++ b/src/library/scala/reflect/generic/Trees.scala @@ -296,23 +296,23 @@ trait Trees { self: Universe => case class Block(stats: List[Tree], expr: Tree) extends TermTree - /** Case clause in a pattern match, eliminated by TransMatch + /** Case clause in a pattern match, eliminated during explicitouter * (except for occurrences in switch statements) */ case class CaseDef(pat: Tree, guard: Tree, body: Tree) extends Tree - /** Alternatives of patterns, eliminated by TransMatch, except for + /** Alternatives of patterns, eliminated by explicitouter, except for * occurrences in encoded Switch stmt (=remaining Match(CaseDef(...)) */ case class Alternative(trees: List[Tree]) extends TermTree - /** Repetition of pattern, eliminated by TransMatch */ + /** Repetition of pattern, eliminated by explicitouter */ case class Star(elem: Tree) extends TermTree - /** Bind of a variable to a rhs pattern, eliminated by TransMatch + /** Bind of a variable to a rhs pattern, eliminated by explicitouter * * @param name * @param body @@ -343,12 +343,11 @@ trait Trees { self: Universe => extends TermTree /** <p> - * Pattern matching expression (before <code>TransMatch</code>) - * Switch statements (after TransMatch) + * Pattern matching expression (before explicitouter) + * Switch statements (after explicitouter) * </p> * <p> - * After <code>TransMatch</code>, cases will satisfy the following - * constraints: + * After explicitouter, cases will satisfy the following constraints: * </p> * <ul> * <li>all guards are EmptyTree,</li> diff --git a/src/manual/scala/man1/scalac.scala b/src/manual/scala/man1/scalac.scala index d2f6183356..e22abdd1eb 100644 --- a/src/manual/scala/man1/scalac.scala +++ b/src/manual/scala/man1/scalac.scala @@ -242,9 +242,6 @@ object scalac extends Command { MItalic("uncurry"), "uncurry function types and applications"), Definition( - MItalic("transmatch"), - "translate match expressions"), - Definition( MItalic("lambdalift"), "lambda lifter"), Definition( diff --git a/test/files/neg/patmatexhaust.check b/test/files/neg/patmatexhaust.check index ca769300c0..83c4279b0a 100644 --- a/test/files/neg/patmatexhaust.check +++ b/test/files/neg/patmatexhaust.check @@ -13,7 +13,7 @@ missing combination Kult Kult missing combination Qult Qult def ma3(x:Mult) = (x,x) match { // not exhaustive - ^ + ^ patmatexhaust.scala:49: warning: match is not exhaustive! missing combination Gp missing combination Gu diff --git a/test/files/run/t3887.scala b/test/files/run/t3887.scala new file mode 100644 index 0000000000..16ce983efc --- /dev/null +++ b/test/files/run/t3887.scala @@ -0,0 +1,16 @@ +object Test { + def main(args: Array[String]) { + assert( matchPair(1) ) + assert( !matchPair(2) ) + } + + def matchPair(i: Int) = { + (i, "abc") match { + case this.option1 => true + case _ => false + } + } + + val option1: (Int, String) = (1, "abc") + +} diff --git a/test/files/run/t3888.scala b/test/files/run/t3888.scala new file mode 100644 index 0000000000..ecdf87e925 --- /dev/null +++ b/test/files/run/t3888.scala @@ -0,0 +1,26 @@ +object Test { + + val T1 = new P + private[this] val T2 = T1 + + def m1 = + (1, 2) match { + case T1 => true + case _ => false + } + + def m2 = + (1, 2) match { + case T2 => true + case _ => false + } + + def main(args: Array[String]) = { + assert( m1 ) + assert( m2 ) + } +} + +class P extends Pair(1, 1) { + override def equals(x: Any) = true +}
\ No newline at end of file diff --git a/test/files/run/tuple-match.check b/test/files/run/tuple-match.check new file mode 100644 index 0000000000..0c1ea0005b --- /dev/null +++ b/test/files/run/tuple-match.check @@ -0,0 +1,8 @@ +4, #3 +4, #2 +4, #4 +3, #2 +2, #2 +1, #1 +FOUR +THREE diff --git a/test/files/run/tuple-match.scala b/test/files/run/tuple-match.scala new file mode 100644 index 0000000000..fcaefbff5b --- /dev/null +++ b/test/files/run/tuple-match.scala @@ -0,0 +1,27 @@ +object Test { + val FOUR = (-1, -2, -3, "bingo donkey vegas") + val THREE = (-1, -2, -3) + + def f(x: Any) = x match { + case FOUR => "FOUR" + case (_, _, 3, _) => "4, #3" + case (_, 2, _, _) => "4, #2" + case (_, 2, _) => "3, #2" + case Tuple1(1) => "1, #1" + case (_, _, _, 4) => "4, #4" + case THREE => "THREE" + case (_, 2) => "2, #2" + case _ => "default" + } + + def main(args: Array[String]): Unit = { + println(f((1, 2, 3, 4))) + println(f((1, 2, 30, 4))) + println(f((1, 20, 30, 4))) + println(f((1, 2, 3))) + println(f((1, 2))) + println(f(Tuple1(1))) + println(f((-1, -2, -3, "bingo donkey vegas"))) + println(f((-1, -2, -3))) + } +} |