summaryrefslogtreecommitdiff
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
parent87878dd86046ea12efe4969d3501f6c1c55f4123 (diff)
downloadscala-39b388ce8a53916e921ac4c807b2282ace2b7caa.tar.gz
scala-39b388ce8a53916e921ac4c807b2282ace2b7caa.tar.bz2
scala-39b388ce8a53916e921ac4c807b2282ace2b7caa.zip
Fixed tailcalls and line numbers.
-rw-r--r--sources/scala/tools/nsc/backend/icode/GenICode.scala32
-rw-r--r--sources/scala/tools/nsc/backend/jvm/GenJVM.scala4
-rw-r--r--sources/scala/tools/nsc/transform/TailCalls.scala50
-rw-r--r--sources/scala/tools/nsc/util/SourceFile.scala2
4 files changed, 62 insertions, 26 deletions
diff --git a/sources/scala/tools/nsc/backend/icode/GenICode.scala b/sources/scala/tools/nsc/backend/icode/GenICode.scala
index 1dc5b47389..68910ca1bc 100644
--- a/sources/scala/tools/nsc/backend/icode/GenICode.scala
+++ b/sources/scala/tools/nsc/backend/icode/GenICode.scala
@@ -489,9 +489,14 @@ abstract class GenICode extends SubComponent {
genConversion(l, r, ctx1, cast)
else if (l.isValueType) {
ctx1.bb.emit(DROP(l), fun.pos);
- ctx1.bb.emit(CONSTANT(Constant(false)))
+ if (cast) {
+ ctx1.bb.emit(NEW(REFERENCE(definitions.getClass("ClassCastException"))));
+ ctx1.bb.emit(DUP(ANY_REF_CLASS));
+ ctx1.bb.emit(THROW());
+ } else
+ ctx1.bb.emit(CONSTANT(Constant(false)))
}
- else if (r.isValueType)
+ else if (r.isValueType /*|| r.isArrayType */)
genBoxedConversion(l, r, ctx1, cast)
else
genCast(l, r, ctx1, cast);
@@ -902,14 +907,29 @@ abstract class GenICode extends SubComponent {
}
}
+ /** Generate a conversion from a reference type to a value type, like in
+ * Any -> Array[Int] or Any -> Int
+ */
def genBoxedConversion(from: TypeKind, to: TypeKind, ctx: Context, cast: Boolean) = {
- assert(to.isValueType, "Expecting conversion to value type: " + to);
- val boxedCls = definitions.boxedClass(to.toType.symbol);
+ assert(to.isValueType || to.isArrayType, "Expecting conversion to value type: " + to);
+
+ val boxedCls = to match {
+ case ARRAY(ARRAY(_)) | ARRAY(REFERENCE(_)) =>
+ definitions.BoxedObjectArrayClass;
+ case ARRAY(elem) =>
+ definitions.boxedArrayClass(elem.toType.symbol)
+ case _ =>
+ definitions.boxedClass(to.toType.symbol);
+ }
+
if (cast) {
ctx.bb.emit(CHECK_CAST(REFERENCE(boxedCls)));
- ctx.bb.emit(LOAD_FIELD(definitions.getMember(boxedCls, "value"), false));
- } else
+ ctx.bb.emit(CONSTANT(Constant(definitions.signature(to.toType))));
+ ctx.bb.emit(CALL_METHOD(definitions.getMember(boxedCls, "unbox"),
+ Dynamic));
+ } else {
ctx.bb.emit(IS_INSTANCE(REFERENCE(boxedCls)));
+ }
}
def genCast(from: TypeKind, to: TypeKind, ctx: Context, cast: Boolean) = {
diff --git a/sources/scala/tools/nsc/backend/jvm/GenJVM.scala b/sources/scala/tools/nsc/backend/jvm/GenJVM.scala
index 203f2186a5..d03e647616 100644
--- a/sources/scala/tools/nsc/backend/jvm/GenJVM.scala
+++ b/sources/scala/tools/nsc/backend/jvm/GenJVM.scala
@@ -555,7 +555,9 @@ abstract class GenJVM extends SubComponent {
}
crtPC = jcode.getPC();
- val crtLine = instr.pos; //clasz.cunit.position(instr.pos).line;
+ val crtLine = try { clasz.cunit.position(instr.pos).line; } catch {
+ case _: Error => -1;
+ }
if (crtLine != lastLineNr &&
crtPC > lastMappedPC) {
jcode.completeLineNumber(lastMappedPC, crtPC, crtLine);
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"
diff --git a/sources/scala/tools/nsc/util/SourceFile.scala b/sources/scala/tools/nsc/util/SourceFile.scala
index be9cbbe4a2..ac6f2baf8c 100644
--- a/sources/scala/tools/nsc/util/SourceFile.scala
+++ b/sources/scala/tools/nsc/util/SourceFile.scala
@@ -47,7 +47,7 @@ class SourceFile(_file : AbstractFile, _content : Array[Char]) {
// constants
// NOTE: all indexes are based on zero!!!!
- override def toString(): String = file.getName() + ":" + content.length;
+ override def toString(): String = file.getName() /* + ":" + content.length */ ;
object line {