diff options
author | David MacIver <david.maciver@gmail.com> | 2008-10-26 15:55:23 +0000 |
---|---|---|
committer | David MacIver <david.maciver@gmail.com> | 2008-10-26 15:55:23 +0000 |
commit | 833c65eb0960bab1972e64a78a6389aff6845b71 (patch) | |
tree | bc5e36e86ad2c47e750efd5f54b9a5f944c3fbc7 /src | |
parent | ced4ddfef6b26f5aa84960289bb08c4cb883d071 (diff) | |
download | scala-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.
Diffstat (limited to 'src')
5 files changed, 62 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) |