summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBurak Emir <emir@epfl.ch>2005-07-31 19:00:08 +0000
committerBurak Emir <emir@epfl.ch>2005-07-31 19:00:08 +0000
commite59ae197eb1441406135a89ab042e01c27fe7557 (patch)
tree2728e7a609684b34e449082aa4305ec11a0b694f
parent03f703627ae1e4fd9ad50a8677defaaf7fbdee60 (diff)
downloadscala-e59ae197eb1441406135a89ab042e01c27fe7557.tar.gz
scala-e59ae197eb1441406135a89ab042e01c27fe7557.tar.bz2
scala-e59ae197eb1441406135a89ab042e01c27fe7557.zip
bugfix, optimized ArrayValue(x@_*)
-rw-r--r--sources/scala/tools/nsc/matching/AlgebraicMatchers.scala12
-rw-r--r--sources/scala/tools/nsc/matching/PatternMatchers.scala46
-rw-r--r--sources/scala/tools/nsc/matching/PatternNodes.scala4
-rw-r--r--sources/scala/tools/nsc/matching/TransMatcher.scala169
4 files changed, 137 insertions, 94 deletions
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);
}