summaryrefslogtreecommitdiff
path: root/sources/scala/tools/nsc/transform/TailCalls.scala
diff options
context:
space:
mode:
authorIulian Dragos <jaguarul@gmail.com>2005-11-23 14:40:23 +0000
committerIulian Dragos <jaguarul@gmail.com>2005-11-23 14:40:23 +0000
commit39b388ce8a53916e921ac4c807b2282ace2b7caa (patch)
tree93b3b71b00eb542b38483ebc24d763a8afaeb6f1 /sources/scala/tools/nsc/transform/TailCalls.scala
parent87878dd86046ea12efe4969d3501f6c1c55f4123 (diff)
downloadscala-39b388ce8a53916e921ac4c807b2282ace2b7caa.tar.gz
scala-39b388ce8a53916e921ac4c807b2282ace2b7caa.tar.bz2
scala-39b388ce8a53916e921ac4c807b2282ace2b7caa.zip
Fixed tailcalls and line numbers.
Diffstat (limited to 'sources/scala/tools/nsc/transform/TailCalls.scala')
-rw-r--r--sources/scala/tools/nsc/transform/TailCalls.scala50
1 files changed, 32 insertions, 18 deletions
diff --git a/sources/scala/tools/nsc/transform/TailCalls.scala b/sources/scala/tools/nsc/transform/TailCalls.scala
index 2a61685d00..3a1e38b9b7 100644
--- a/sources/scala/tools/nsc/transform/TailCalls.scala
+++ b/sources/scala/tools/nsc/transform/TailCalls.scala
@@ -5,6 +5,8 @@
// $Id$
package scala.tools.nsc.transform;
+import scala.tools.nsc.symtab.Flags;
+
/** Perform tail recursive call elimination.
*/
abstract class TailCalls extends Transform
@@ -67,7 +69,7 @@ abstract class TailCalls extends Transform
var label: Symbol = NoSymbol;
/** The expected type arguments of self-recursive calls */
- var types: List[Type] = Nil;
+ var tparams: List[Symbol] = Nil;
/** Tells whether we are in a (possible) tail position */
var tailPos = false;
@@ -79,9 +81,9 @@ abstract class TailCalls extends Transform
this();
this.currentMethod = that.currentMethod;
this.label = that.label;
- this.types = that.types;
+ this.tparams = that.tparams;
this.tailPos = that.tailPos;
- this.accessed = that.accessed;
+ this.accessed = that.accessed;
}
/** Create a new method symbol for the current method and store it in
@@ -93,7 +95,7 @@ abstract class TailCalls extends Transform
}
override def toString(): String = {
- "" + currentMethod.name + " types: " + types + " tailPos: " + tailPos +
+ "" + currentMethod.name + " tparams: " + tparams + " tailPos: " + tailPos +
" accessed: " + accessed + "\nLabel: " + label + "\nLabel type: " + label.info;
}
}
@@ -127,15 +129,18 @@ abstract class TailCalls extends Transform
newCtx.label.setInfo(tree.symbol.info);
newCtx.tailPos = true;
- val t1 = if (newCtx.currentMethod.isFinal) {
- newCtx.types = Nil;
-
- newCtx.currentMethod.tpe match {
- case PolyType(tparams, result) =>
- newCtx.types = tparams map (s => s.tpe);
- newCtx.label.setInfo(result);
-
- case _ => ;
+ val t1 = if (newCtx.currentMethod.isFinal ||
+ newCtx.currentMethod.enclClass.hasFlag(Flags.MODULE)) {
+ newCtx.tparams = Nil;
+ log(" Considering " + name + " for tailcalls");
+ tree.symbol.tpe match {
+ case PolyType(tpes, restpe) =>
+ newCtx.tparams = tparams map (.symbol);
+ newCtx.label.setInfo(
+ restpe.substSym(tpes, tparams map (.symbol)));
+ log("adding types: " + newCtx.tparams);
+ log("setting return resultType to: " + newCtx.label.tpe);
+ case _ => ();
}
var newRHS = transform(rhs, newCtx);
@@ -187,7 +192,8 @@ abstract class TailCalls extends Transform
throw new RuntimeException("We should've never gotten inside a pattern");
case Function(vparams, body) =>
- throw new RuntimeException("Anonymous function should not exist at this point");
+ tree
+ //throw new RuntimeException("Anonymous function should not exist at this point. at: " + unit.position(tree.pos));
case Assign(lhs, rhs) => super.transform(tree);
case If(cond, thenp, elsep) =>
@@ -204,11 +210,11 @@ abstract class TailCalls extends Transform
case Apply(tapply @ TypeApply(fun, targs), vargs) =>
if ( ctx.currentMethod.isFinal &&
ctx.tailPos &&
- isSameTypes(ctx.types, targs map (.tpe)) &&
+ isSameTypes(ctx.tparams, targs map (.tpe.symbol)) &&
isRecursiveCall(fun))
- rewriteTailCall(fun, transformTrees(vargs, mkContext(ctx, false)));
- else
- copy.Apply(tree, tapply, transformTrees(vargs, mkContext(ctx, false)));
+ rewriteTailCall(fun, transformTrees(vargs, mkContext(ctx, false)))
+ else
+ copy.Apply(tree, tapply, transformTrees(vargs, mkContext(ctx, false)));
case TypeApply(fun, args) =>
super.transform(tree);
@@ -250,6 +256,14 @@ abstract class TailCalls extends Transform
Apply(Ident(ctx.label), args)));
}
+ private def isSameTypes(ts1: List[Symbol], ts2: List[Symbol]): Boolean = {
+ def isSameType(t1: Symbol, t2: Symbol) = {
+ log("" + t1 + " vs " + t2);
+ t1 == t2
+ }
+ List.forall2(ts1, ts2)(isSameType)
+ }
+
/** Return true if the fun tree refers to the same method as the one
* saved in ctx. If it is a method call, we check that it is applied to
* "this"