From e59ae197eb1441406135a89ab042e01c27fe7557 Mon Sep 17 00:00:00 2001 From: Burak Emir Date: Sun, 31 Jul 2005 19:00:08 +0000 Subject: bugfix, optimized ArrayValue(x@_*) --- .../tools/nsc/matching/AlgebraicMatchers.scala | 12 +- .../scala/tools/nsc/matching/PatternMatchers.scala | 46 ++++-- .../scala/tools/nsc/matching/PatternNodes.scala | 4 +- .../scala/tools/nsc/matching/TransMatcher.scala | 169 +++++++++++---------- 4 files changed, 137 insertions(+), 94 deletions(-) (limited to 'sources') diff --git a/sources/scala/tools/nsc/matching/AlgebraicMatchers.scala b/sources/scala/tools/nsc/matching/AlgebraicMatchers.scala index d1a3808039..729b39e6ee 100644 --- a/sources/scala/tools/nsc/matching/AlgebraicMatchers.scala +++ b/sources/scala/tools/nsc/matching/AlgebraicMatchers.scala @@ -33,8 +33,16 @@ trait AlgebraicMatchers : TransMatcher { super.initialize( _m.selector, _m.owner, doBinding ); val it = cases.elements; - while (it.hasNext) - enter(it.next); + while (it.hasNext) { + val cdef = it.next; + /* + if(cdef != null) + Console.println("algebraic matcher: "+cdef.toString()); // DEBUG + else + scala.Predef.error("got CaseDef null in alg matcher!"); + */ + enter(cdef); + } //if (unit.global.log()) { // unit.global.log("internal pattern matching structure"); diff --git a/sources/scala/tools/nsc/matching/PatternMatchers.scala b/sources/scala/tools/nsc/matching/PatternMatchers.scala index 6ef2f8d973..7d9c01ec8d 100644 --- a/sources/scala/tools/nsc/matching/PatternMatchers.scala +++ b/sources/scala/tools/nsc/matching/PatternMatchers.scala @@ -69,6 +69,7 @@ trait PatternMatchers: (TransMatcher with PatternNodes) extends AnyRef with Patt selector.tpe.widen, Ident(root.symbol).setType(root.tpe)); this.resultVar = owner.newVariable(Flags.MUTABLE, + //"result").setType( resultType ); "result").setInfo( resultType ); //Console.println("resultType = "+resultType); this.owner = owner; @@ -164,13 +165,20 @@ trait PatternMatchers: (TransMatcher with PatternNodes) extends AnyRef with Patt * (( tree.args.length == 1 ) && tree.args(0).isInstanceOf[Sequence]) * but fails */ - protected def isSeqApply( tree: Apply ): Boolean = - (( tree.args.length == 1 ) && //tree.args(0).isInstanceOf[Sequence]) - tree.args(0).isInstanceOf[ArrayValue]) - && (tree.tpe.symbol.flags & Flags.CASE) == 0; + protected def isSeqApply( tree: Apply ): Boolean = { + // Console.print("isSeqApply? "+tree.toString()); + // val res = + tree match { + case Apply(_, List(ArrayValue(_,_))) => (tree.tpe.symbol.flags & Flags.CASE) == 0 + case _ => false; + } + //Console.println(res); + //res; + } protected def patternNode(tree:Tree , header:Header , env: CaseEnv ): PatternNode = { - //Console.println("patternNode("+tree+","+header+")"); + //if(tree!=null) Console.println("patternNode("+tree+","+header+")"); + //else scala.Predef.error("got null tree in patternNode"); //Console.println("tree.tpe "+tree.tpe); //Console.println("tree.getClass() "+tree.getClass()); tree match { @@ -223,7 +231,8 @@ trait PatternMatchers: (TransMatcher with PatternNodes) extends AnyRef with Patt //Console.println("delegating ... "); val res = pConstrPat(tree.pos, tree.tpe); res.and = pHeader(tree.pos, header.getTpe(), header.selector); - res.and.and = pSeqContainerPat(tree.pos, tree.tpe, args(0)); + //res.and.and = pSeqContainerPat(tree.pos, tree.tpe, args(0)); + res.and.and = pSeqContainerPat(tree.pos, tree.tpe, Sequence(args(0).asInstanceOf[ArrayValue].elems)); res; } } else if ((fn.symbol != null) && @@ -240,6 +249,13 @@ trait PatternMatchers: (TransMatcher with PatternNodes) extends AnyRef with Patt */ pConstrPat(tree.pos, tree.tpe); } + case Typed(Ident( nme.WILDCARD ), tpe) => // x@_:Type + val doTest = isSubType(header.getTpe(),tpe.tpe); + if(doTest) + pDefaultPat(tree.pos, tpe.tpe) + else + pConstrPat(tree.pos, tpe.tpe); + case t @ Typed(ident, tpe) => // variable pattern //Console.println("Z"); val doTest = isSubType(header.getTpe(),tpe.tpe); @@ -249,7 +265,11 @@ trait PatternMatchers: (TransMatcher with PatternNodes) extends AnyRef with Patt else pConstrPat(tree.pos, tpe.tpe); } - if ((null != env) && (ident.symbol != defs.PatternWildcard)) + //if(t.expr.symbol == NoSymbol) { + // Console.println(t.toString()); + // scala.Predef.error("go typed pattern with no symbol in "+cunit.toString()); + // } + if ((null != env) /* && (ident.symbol != defs.PatternWildcard) */) node match { case ConstrPat(casted) => env.newBoundVar(t.expr.symbol, @@ -306,7 +326,8 @@ trait PatternMatchers: (TransMatcher with PatternNodes) extends AnyRef with Patt case Literal(Constant(value)) => pConstantPat(tree.pos, tree.tpe, value); - case Sequence(ts) => + //case Sequence(ts) => + case ArrayValue(_, ts) => if ( !delegateSequenceMatching ) { pSequencePat(tree.pos, tree.tpe, ts.length); } else { @@ -326,7 +347,10 @@ trait PatternMatchers: (TransMatcher with PatternNodes) extends AnyRef with Patt pAltPat(tree.pos, subroot.and.asInstanceOf[Header]); case _ => - scala.Predef.error("unit = " + cunit + "; tree = "+tree); + if(tree == null) + scala.Predef.error("unit = " + cunit + "; tree = null"); + else + scala.Predef.error("unit = " + cunit + "; tree = "+tree); } } @@ -359,8 +383,8 @@ trait PatternMatchers: (TransMatcher with PatternNodes) extends AnyRef with Patt pHeader( pos, seqType, t ); } else { //Console.println("NOT FIRSTPOS"); - //Console.println("newHeader :: casted="+casted); - //Console.println("newHeader :: casted.tpe="+casted.tpe); + // Console.println("newHeader :: casted="+casted); + // Console.println("newHeader :: casted.tpe="+casted.tpe); //Console.println("newHeader :: "); val ts = casted.tpe.symbol.asInstanceOf[ClassSymbol] .caseFieldAccessors(index); diff --git a/sources/scala/tools/nsc/matching/PatternNodes.scala b/sources/scala/tools/nsc/matching/PatternNodes.scala index 82ee9efd5d..f16178dbab 100644 --- a/sources/scala/tools/nsc/matching/PatternNodes.scala +++ b/sources/scala/tools/nsc/matching/PatternNodes.scala @@ -328,6 +328,9 @@ trait PatternNodes: TransMatcher { } def newBoundVar(sym:Symbol, tpe: Type, init:Tree ): Unit = { + //if(sym == Symbol.NoSymbol ) { +// scala.Predef.Error("can't add variable with NoSymbol"); +// } // sym.setOwner( owner ); // FIXME should be corrected earlier // @maybe is corrected now? bq if (numVars == boundVars.length) { @@ -335,7 +338,6 @@ trait PatternNodes: TransMatcher { System.arraycopy(boundVars, 0, newVars, 0, numVars); this.boundVars = newVars; } - //sym.setInfo(tpe); sym.setInfo(tpe); this.boundVars(numVars) = ValDef(sym, init.duplicate); numVars = numVars + 1; diff --git a/sources/scala/tools/nsc/matching/TransMatcher.scala b/sources/scala/tools/nsc/matching/TransMatcher.scala index 579181f944..749213bc6c 100644 --- a/sources/scala/tools/nsc/matching/TransMatcher.scala +++ b/sources/scala/tools/nsc/matching/TransMatcher.scala @@ -128,40 +128,6 @@ with RightTracers { class TransMatch extends Transformer { - def isRegular(pat:Tree): Boolean = pat match { - case Alternative(trees) => - trees exists { isRegular } - case Star(_) => true; - - case Ident(_) => false - - case Bind( n, pat1 ) => isRegular( pat1 ) - case Sequence( trees ) => - ( trees.length == 0 ) || (trees exists { isRegular }); - - case ArrayValue( _, trees ) => - ( trees.length == 0 ) || (trees exists { isRegular }); - - case Apply( fn, List(Sequence(List()))) => - false; - - case Apply( fn, trees ) => - ( trees exists { isRegular }) -// && !((trees.length == 1) && TreeInfo.isEmptySequence( trees( 0 ))) - - case Literal(_) => false; - case Select(_,_) => false; - case Typed(_,_) => false; - - //case _ => - // Console.println(pat); - // Console.println(pat.getClass()); - // scala.Predef.error(" what is this ? ") - - - } - - /** a casedef with sequence subpatterns like * * case ..x @ ().. => body @@ -170,74 +136,108 @@ with RightTracers { * * case .. () .. => val x = Nil; body */ - def removeNilVariables( cd: CaseDef ): CaseDef = { - var nilVars:List[Symbol] = Nil; - def remove(pat: Tree): Tree = pat match { - case Alternative( _ ) => pat /* no bind/var allowed! */ - case Star( _ ) => pat /* no bind/var allowed! */ + def isRegular(pats:List[CaseDef]): Pair[List[CaseDef],Boolean] = { + var existsReg = false; + var isReg = false; + var nilVars:List[Symbol] = _; + + 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 /*id.symbol()*/ :: nilVars; - empt - case Bind( id, pat ) => - copy.Bind( pat, id, remove(pat) ); + empt; + case Bind( n, pat1 ) => copy.Bind(pat, n, isRegular1( pat1 )); - case Sequence( trees ) => - copy.Sequence( pat, trees map remove ) + case Sequence( trees ) => + //isReg = isReg || ( trees.length == 0 ); + isReg = true; // cause there are ArrayValues now + copy.Sequence(pat, trees map { isRegular1 }); + + case ArrayValue( tt, List(b @ Bind(id, Star(wc @ Ident(nme.WILDCARD))))) => + //Console.println("OPTIMIZING"); + //Console.println(pat); + //Console.println(pat.tpe); + //Console.println(b.tpe); + b.symbol.setInfo(pat.tpe); + b.setType(pat.tpe); + val res = copy.Bind(b, id, wc); + //Console.println("====>"); + //Console.println(res); + res + + case ArrayValue( s, trees ) => + //Console.println("XXX ArrayValue, trees="+trees); + copy.ArrayValue( pat, s, (trees map { isRegular1 })); - case ArrayValue( tt, trees ) => - copy.ArrayValue( pat, tt, trees map remove ) + case Apply( fn, List(Sequence(List()))) => + pat; - case Apply( fn, args ) => - copy.Apply( pat, fn, args map remove ) + case Apply( fn, trees ) => + //Console.println(" IN isRegular, apply node "+pat.toString()); + //Console.println(" trees are:"+(trees map {x => x.getClass().toString()})); + copy.Apply( pat, fn, ( trees map { isRegular1 }) ) - case Ident(_) => pat - case Literal(_) => pat - case Select(_,_) => pat - case Typed(_,_) => pat + case Literal(_) => pat + case Select(_,_) => pat + case Typed(_,_) => pat - case _ => scala.Predef.error("unknown node"+pat.getClass()); - } + //case _ => + // Console.println(pat); + // Console.println(pat.getClass()); + // scala.Predef.error(" what is this ? ") + } + + var res:List[CaseDef] = Nil; + val it = pats.elements; while(it.hasNext) { + nilVars = Nil; + val cdef = it.next; + val newt = isRegular1(cdef.pat); + existsReg = existsReg || isReg; - cd match { - case CaseDef(pat, guard, body) => - val npat = remove(pat); - val nbody = { - if(nilVars.isEmpty) - body - else - atPos(body.pos)( + val nbody = if(nilVars.isEmpty) cdef.body else + atPos(cdef.body.pos)( Block(nilVars map { x => ValDef(x, Ident(definitions.NilModule)) - }, body) - ) - } - copy.CaseDef(cd, npat, guard, nbody) - } - } + }, cdef.body) + ); - def handle(sel:Tree, cases:List[CaseDef]): Tree = { + res = copy.CaseDef(cdef, newt, cdef.guard, nbody) :: res; + } + Pair(res.reverse, existsReg); + } + + + + def handle(sel:Tree, ocases:List[CaseDef]): Tree = { // 1. is there a regular pattern? - val containsReg = cases.exists { x => isRegular(x.pat) }; + val Pair(cases, containsReg) = isRegular(ocases); // @todo: remove unused variables if(containsReg) { // 2. replace nilVariables //@todo: bring over AlgebraicMatcher - val ncases = cases.map { removeNilVariables }; + /* val matcher = new PartialMatcher { val global: TransMatcher.this.global.type = TransMatcher.this.global; val owner = currentOwner; val selector = sel ; } - //new AlgebraicMatcher() { - // val tm: TransMatcher.this.type = TransMatcher.this; - //}.construct( matcher, ncases ); - //matcher.tree - null + new AlgebraicMatcher() { + val tm: TransMatcher.this.type = TransMatcher.this; + }.construct( matcher, cases ); + matcher.tree + */ + scala.Predef.error("not yet implemented"); } else { val pm = new PatternMatcher(); pm.initialize(sel, currentOwner, true ); @@ -249,16 +249,25 @@ with RightTracers { pm.toTree(); } } - override def transform(tree: Tree): Tree = tree match { case Match(selector, cases) => - val ts = cases map { transform }; + val nselector = transform(selector).setType(selector.tpe); + val ncases = cases map { transform }; + /* + Console.println("TransMatch translating cases: "); + for(val t <- cases) { + Console.println(t.pat.toString()); + Console.println("BODY "+t.body.toString()); + } + */ // @todo: remove from partial matcher TransMatcher.this.currentOwner = currentOwner; TransMatcher.this.resultType = tree.tpe; //Console.println("TransMatcher selector.tpe ="+selector.tpe+")"); - handle(transform(selector).setType(selector.tpe), - ts.asInstanceOf[List[CaseDef]]); + //Console.println("TransMatcher resultType ="+resultType+")"); + val t = handle(nselector, ncases.asInstanceOf[List[CaseDef]]); + //Console.println(t.toString()); + t case _ => super.transform(tree); } -- cgit v1.2.3