diff options
author | Iulian Dragos <jaguarul@gmail.com> | 2005-11-23 14:40:23 +0000 |
---|---|---|
committer | Iulian Dragos <jaguarul@gmail.com> | 2005-11-23 14:40:23 +0000 |
commit | 39b388ce8a53916e921ac4c807b2282ace2b7caa (patch) | |
tree | 93b3b71b00eb542b38483ebc24d763a8afaeb6f1 | |
parent | 87878dd86046ea12efe4969d3501f6c1c55f4123 (diff) | |
download | scala-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.scala | 32 | ||||
-rw-r--r-- | sources/scala/tools/nsc/backend/jvm/GenJVM.scala | 4 | ||||
-rw-r--r-- | sources/scala/tools/nsc/transform/TailCalls.scala | 50 | ||||
-rw-r--r-- | sources/scala/tools/nsc/util/SourceFile.scala | 2 |
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 { |