summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid MacIver <david.maciver@gmail.com>2008-10-26 15:55:23 +0000
committerDavid MacIver <david.maciver@gmail.com>2008-10-26 15:55:23 +0000
commit833c65eb0960bab1972e64a78a6389aff6845b71 (patch)
treebc5e36e86ad2c47e750efd5f54b9a5f944c3fbc7
parentced4ddfef6b26f5aa84960289bb08c4cb883d071 (diff)
downloadscala-833c65eb0960bab1972e64a78a6389aff6845b71.tar.gz
scala-833c65eb0960bab1972e64a78a6389aff6845b71.tar.bz2
scala-833c65eb0960bab1972e64a78a6389aff6845b71.zip
Cleaning up a lot of dead code from regular exp...
Cleaning up a lot of dead code from regular expression patterns. Added a couple tests to verify correctness of cleanup.
-rw-r--r--src/compiler/scala/tools/nsc/Global.scala5
-rw-r--r--src/compiler/scala/tools/nsc/matching/CodeFactory.scala2
-rw-r--r--src/compiler/scala/tools/nsc/matching/ParallelMatching.scala2
-rw-r--r--src/compiler/scala/tools/nsc/matching/TransMatcher.scala255
-rw-r--r--src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala3
-rw-r--r--test/files/run/matcharraytail.check2
-rw-r--r--test/files/run/matcharraytail.scala7
-rw-r--r--test/files/run/matchemptyarray.check1
-rw-r--r--test/files/run/matchemptyarray.scala5
9 files changed, 77 insertions, 205 deletions
diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala
index b942d81591..ac2be354eb 100644
--- a/src/compiler/scala/tools/nsc/Global.scala
+++ b/src/compiler/scala/tools/nsc/Global.scala
@@ -23,7 +23,6 @@ import plugins.Plugins
import ast._
import ast.parser._
import typechecker._
-//import matching.TransMatcher
import transform._
import backend.icode.{ICodes, GenICode, Checkers}
import backend.ScalaPrimitives
@@ -313,10 +312,6 @@ class Global(var settings: Settings, var reporter: Reporter) extends SymbolTable
val global: Global.this.type = Global.this
} with TailCalls
- //object transMatcher extends {
- // val global: Global.this.type = Global.this
- //} with TransMatcher
-
// object checkDefined extends {
// val global: Global.this.type = Global.this
// } with CheckDefined
diff --git a/src/compiler/scala/tools/nsc/matching/CodeFactory.scala b/src/compiler/scala/tools/nsc/matching/CodeFactory.scala
index 3d565b7eaa..1c1ab6567e 100644
--- a/src/compiler/scala/tools/nsc/matching/CodeFactory.scala
+++ b/src/compiler/scala/tools/nsc/matching/CodeFactory.scala
@@ -71,7 +71,7 @@ trait CodeFactory {
final def seqElement(sel:Tree, ix: Int) =
typed { Apply(Select(sel, sel.tpe.member(nme.apply)), List(Literal(Constant(ix)))) }
- /** for tree of sequence type, returns boolean tree that has length i */
+ /** for tree of sequence type, returns boolean tree testing that the sequence has length i */
final def seqHasLength(sel: Tree, ntpe: Type, i: Int) =
typed(
Equals(
diff --git a/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala b/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala
index 02495dd61a..213cde19c8 100644
--- a/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala
+++ b/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala
@@ -599,7 +599,7 @@ trait ParallelMatching {
}
}
- /** handle sequence pattern and ArrayValue (but not star patterns)
+ /** handle sequence pattern and ArrayValue with star patterns
*/
final class MixSequenceStar(scrutinee:Symbol, column:List[Tree], rest:Rep)(implicit rep:RepFactory) extends MixSequence(scrutinee,column,rest) {
// in principle, we could optimize more, but variable binding gets complicated (@todo use finite state methods instead)
diff --git a/src/compiler/scala/tools/nsc/matching/TransMatcher.scala b/src/compiler/scala/tools/nsc/matching/TransMatcher.scala
index 941d669438..ce31e50f07 100644
--- a/src/compiler/scala/tools/nsc/matching/TransMatcher.scala
+++ b/src/compiler/scala/tools/nsc/matching/TransMatcher.scala
@@ -31,217 +31,82 @@ trait TransMatcher { self: transform.ExplicitOuter with PatternNodes with Parall
final val settings_squeeze = settings.Xsqueeze.value == "on"
final val settings_casetags = settings.Xcasetags.value == "on"
- final def hasRegularPattern(pats1: List[Tree]): Boolean = {
- var pats = pats1; while(pats ne Nil) {
- if(isRegularPattern(pats.head)) { return true; } else { pats = pats.tail }
- }
- return false
- }
-
- final def isRegularPattern(pat: Tree): Boolean = {
- pat match {
- case Alternative(trees) => hasRegularPattern(trees)
- case Star(t) => true
- case Ident(_) => false
- case Bind(n, pat1) => isRegularPattern(pat1)
- case Sequence(trees) => true // cause there are ArrayValues now
- case ArrayValue(tt, trees) => hasRegularPattern(trees)
- case Apply(fn, trees) => hasRegularPattern(trees)
- case Literal(_) => false
- case Select(_, _) => false
- case Typed(_, _) => false
- case UnApply(_,trees) => hasRegularPattern(trees)
- }
- }
-
- // @todo: this should be isNotRegular :-/ premature opt src of all evil
- // check special case Seq(p1,...,pk,_*) where pi not regular
+ // check special case Seq(p1,...,pk,_*)
protected def isRightIgnoring(p: ArrayValue): Boolean = {
- def isDefaultStar(p: Tree): Boolean = p match {
+ def isDefaultStar(tree: Tree): Boolean = tree match {
case Bind(_, q) => isDefaultStar(q)
case Star(Ident(nme.WILDCARD)) => true
case _ => false
}
- 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)
- }
- }
-
- /** a casedef with sequence subpatterns like
- *
- * case ..x @ ().. => body
- *
- * should be replaced straight away with
- *
- * case .. () .. => val x = Nil; body
- */
- def isRegular(pats: List[CaseDef]): (List[CaseDef],Boolean) = {
- var existsReg = false
- var isReg = false
- var nilVars: List[Symbol] = null
-
- def isRegular1(pat: Tree): Tree = pat match {
- case Alternative(trees) =>
- copy.Alternative(pat, trees map { isRegular1 })
-
- case Star(t) =>
- isReg = true; copy.Star(pat, isRegular1(t))
-
- case Ident(_) =>
- pat
-
- case Bind(id, empt @ Sequence(List())) =>
- nilVars = pat.symbol :: nilVars
- empt
-
- case Bind(n, pat1) =>
- copy.Bind(pat, n, isRegular1(pat1))
-
- case Sequence(trees) =>
- isReg = true
- copy.Sequence(pat, trees map { isRegular1 })
-
- case UnApply(fn, args) => copy.UnApply(pat, fn, args map { isRegular1 })
-
- 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)
-
- 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)
- copy.Apply(pat, fn, List(copy.Bind(b, id, wc)))
-
- case av @ ArrayValue(s, trees) =>
- if (isRightIgnoring(av)) pat
- else copy.ArrayValue(pat, s, (trees map { isRegular1 }))
- case Apply(fn, List(Sequence(List()))) =>
- pat
-
- case Apply(fn, trees) =>
- copy.Apply(pat, fn, (trees map { isRegular1 }))
-
- case Literal(_) =>
- pat
-
- case Select(_, _) =>
- pat
-
- case Typed(_, _) =>
- pat
-
- case This(_) =>
- val stpe = mkThisType(pat.tpe.typeSymbol)
- Typed(Ident(nme.WILDCARD) setType stpe, TypeTree(stpe))
- }
-
- var res = new ListBuffer[CaseDef]
- val it = pats.elements; while (it.hasNext) {
- nilVars = Nil
- val cdef = it.next
- val newt = isRegular1(cdef.pat)
- existsReg = existsReg || isReg
-
- val nbody = if (nilVars.isEmpty) cdef.body else
- atPos(cdef.body.pos)(
- Block(nilVars map {
- x => ValDef(x, Ident(definitions.NilModule))
- }, cdef.body)
- )
-
- res += copy.CaseDef(cdef, newt, cdef.guard, nbody)
- }
- (res.toList, existsReg)
+ !p.elems.isEmpty && isDefaultStar(p.elems.last)
}
/** handles all translation of pattern matching
*/
- 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))
+ def handlePattern(selector: Tree, cases: List[CaseDef], doCheckExhaustive: Boolean, owner: Symbol, handleOuter: Tree => Tree): Tree = {
+ implicit val theOwner = owner
+ if (settings_debug) {
+ Console.println("****")
+ Console.println("**** initalize, selector = "+selector+" selector.tpe = "+selector.tpe)
+ Console.println("**** doCheckExhaustive == "+doCheckExhaustive)
+ }
- 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(ti.pos, "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 {
- tmps += root
- vds += vdef
+ implicit val rep = new RepFactory(handleOuter)
+ 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(ti.pos, "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
}
- val irep = initRep(tmps.toList, cases, rep)
+ theFailTree = ThrowMatchError(selector.pos, copy.Apply(app, fn, tmps.toList map mkIdent))
+ case _ =>
+ tmps += root
+ vds += vdef
+ } 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{Block(vds.toList, mch)}
- // cannot use squeezedBlock because of side-effects, see t275
- //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
- }
- dfatree = rep.cleanup(dfatree)
- resetTrav.traverse(dfatree)
- dfatree
- } catch {
- case ex: FatalError => ex.printStackTrace(); throw ex
+ val mch = typed{ repToTree(irep)}
+ var dfatree = typed{Block(vds.toList, mch)}
+ // cannot use squeezedBlock because of side-effects, see t275
+ 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
}
+ dfatree = rep.cleanup(dfatree)
+ resetTrav.traverse(dfatree)
+ dfatree
}
object resetTrav extends Traverser {
diff --git a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala
index ed370bc48e..0451509a07 100644
--- a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala
+++ b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala
@@ -482,9 +482,6 @@ abstract class ExplicitOuter extends InfoTransform with TransMatcher with Patter
}
ExplicitOuter.this.resultType = tree.tpe
- //Console.println("TransMatcher currentOwner ="+currentOwner+")")
- //Console.println("TransMatcher selector.tpe ="+selector.tpe+")")
- //Console.println("TransMatcher resultType ="+resultType+")")
//println("handle pattern = "+nselector+"/"+ncases.toList+"/"+currentOwner+"/"+tree.tpe)
val t_untyped = handlePattern(nselector, ncases.toList, checkExhaustive, currentOwner, transform)
diff --git a/test/files/run/matcharraytail.check b/test/files/run/matcharraytail.check
new file mode 100644
index 0000000000..049db39a07
--- /dev/null
+++ b/test/files/run/matcharraytail.check
@@ -0,0 +1,2 @@
+Array(foo, bar, baz)
+Array(bar, baz)
diff --git a/test/files/run/matcharraytail.scala b/test/files/run/matcharraytail.scala
new file mode 100644
index 0000000000..cdd79acda3
--- /dev/null
+++ b/test/files/run/matcharraytail.scala
@@ -0,0 +1,7 @@
+object Test extends Application{
+ Array("foo", "bar", "baz") match {
+ case x@Array("foo", bar @_*) => println(x.toString); println(bar.toString);
+ case Array(x, y, z) => println("shouldn't have fallen through");
+ case _ => println("default case?!");
+ }
+}
diff --git a/test/files/run/matchemptyarray.check b/test/files/run/matchemptyarray.check
new file mode 100644
index 0000000000..815225fc64
--- /dev/null
+++ b/test/files/run/matchemptyarray.check
@@ -0,0 +1 @@
+Array()
diff --git a/test/files/run/matchemptyarray.scala b/test/files/run/matchemptyarray.scala
new file mode 100644
index 0000000000..63abf74b65
--- /dev/null
+++ b/test/files/run/matchemptyarray.scala
@@ -0,0 +1,5 @@
+object Test extends Application{
+ Array[String]() match {
+ case x@Array() => println(x.toString());
+ }
+}