diff options
author | Paul Phillips <paulp@improving.org> | 2012-03-14 10:00:30 -0700 |
---|---|---|
committer | Paul Phillips <paulp@improving.org> | 2012-03-14 10:08:36 -0700 |
commit | 3ab383ae01a66208df4955bf2117dd2ea8eb2afe (patch) | |
tree | ac83e7e89310955ccbc317f57f34165f9781117c /src/continuations | |
parent | b6dde2b6cf5f66e96fc92c09c1fbe3b4a8dc348c (diff) | |
parent | 5dca64cefeed4bc3289e641949b103e5e806aa32 (diff) | |
download | scala-3ab383ae01a66208df4955bf2117dd2ea8eb2afe.tar.gz scala-3ab383ae01a66208df4955bf2117dd2ea8eb2afe.tar.bz2 scala-3ab383ae01a66208df4955bf2117dd2ea8eb2afe.zip |
Merge branch 'master' into merge-inline
Conflicts:
lib/scala-compiler.jar.desired.sha1
lib/scala-library-src.jar.desired.sha1
lib/scala-library.jar.desired.sha1
src/compiler/scala/reflect/internal/Definitions.scala
src/compiler/scala/reflect/internal/Importers.scala
src/compiler/scala/reflect/internal/Symbols.scala
src/compiler/scala/reflect/internal/Trees.scala
src/compiler/scala/reflect/internal/Types.scala
src/compiler/scala/tools/nsc/Global.scala
src/compiler/scala/tools/nsc/transform/Erasure.scala
src/compiler/scala/tools/nsc/transform/LiftCode.scala
src/compiler/scala/tools/nsc/transform/UnCurry.scala
src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
src/compiler/scala/tools/nsc/typechecker/Typers.scala
test/files/run/programmatic-main.check
test/files/speclib/instrumented.jar.desired.sha1
Diffstat (limited to 'src/continuations')
4 files changed, 93 insertions, 44 deletions
diff --git a/src/continuations/plugin/scala/tools/selectivecps/CPSAnnotationChecker.scala b/src/continuations/plugin/scala/tools/selectivecps/CPSAnnotationChecker.scala index ab1510bd7f..af0d768607 100644 --- a/src/continuations/plugin/scala/tools/selectivecps/CPSAnnotationChecker.scala +++ b/src/continuations/plugin/scala/tools/selectivecps/CPSAnnotationChecker.scala @@ -50,7 +50,27 @@ abstract class CPSAnnotationChecker extends CPSUtils { // @plus @cps will fall through and compare the @cps type args // @cps parameters must match exactly - (annots1 corresponds annots2)(_.atp <:< _.atp) + if ((annots1 corresponds annots2)(_.atp <:< _.atp)) + return true + + // Need to handle uninstantiated type vars specially: + + // g map (x => x) with expected type List[Int] @cps + // results in comparison ?That <:< List[Int] @cps + + // Instantiating ?That to an annotated type would fail during + // transformation. + + // Instead we force-compare tpe1 <:< tpe2.withoutAnnotations + // to trigger instantiation of the TypeVar to the base type + + // This is a bit unorthodox (we're only supposed to look at + // annotations here) but seems to work. + + if (!annots2.isEmpty && !tpe1.isGround) + return tpe1 <:< tpe2.withoutAnnotations + + false } /** Refine the computed least upper bound of a list of types. @@ -222,6 +242,9 @@ abstract class CPSAnnotationChecker extends CPSUtils { case OverloadedType(pre, alts) => OverloadedType(pre, alts.map((sym: Symbol) => updateAttributes(pre.memberType(sym), annots))) */ + case OverloadedType(pre, alts) => tpe //reconstruct correct annotations later + case MethodType(params, restpe) => tpe + case PolyType(params, restpe) => tpe case _ => assert(childAnnots forall (_ matches MarkerCPSTypes), childAnnots) /* @@ -229,7 +252,7 @@ abstract class CPSAnnotationChecker extends CPSUtils { plus + [] = plus cps + [] = cps plus cps + [] = plus cps - minus cps + [] = minus cp + minus cps + [] = minus cps synth cps + [] = synth cps // <- synth on left - does it happen? [] + cps = cps @@ -313,18 +336,34 @@ abstract class CPSAnnotationChecker extends CPSUtils { def single(xs: List[AnnotationInfo]) = xs match { case List(x) => x case _ => - global.globalError("not a single cps annotation: " + xs)// FIXME: error message + global.globalError("not a single cps annotation: " + xs) xs(0) } + + def emptyOrSingleList(xs: List[AnnotationInfo]) = if (xs.isEmpty) Nil else List(single(xs)) def transChildrenInOrder(tree: Tree, tpe: Type, childTrees: List[Tree], byName: List[Tree]) = { - val children = childTrees.flatMap { t => + def inspect(t: Tree): List[AnnotationInfo] = { if (t.tpe eq null) Nil else { + val extra: List[AnnotationInfo] = t.tpe match { + case _: MethodType | _: PolyType | _: OverloadedType => + // method types, poly types and overloaded types do not obtain cps annotions by propagation + // need to reconstruct transitively from their children. + t match { + case Select(qual, name) => inspect(qual) + case Apply(fun, args) => (fun::(transArgList(fun,args).flatten)) flatMap inspect + case TypeApply(fun, args) => (fun::(transArgList(fun,args).flatten)) flatMap inspect + case _ => Nil + } + case _ => Nil + } + val types = cpsParamAnnotation(t.tpe) // TODO: check that it has been adapted and if so correctly - if (types.isEmpty) Nil else List(single(types)) + extra ++ emptyOrSingleList(types) } } + val children = childTrees flatMap inspect val newtpe = updateAttributesFromChildren(tpe, children, byName) @@ -359,9 +398,15 @@ abstract class CPSAnnotationChecker extends CPSUtils { transChildrenInOrder(tree, tpe, qual::(transArgList(fun, args).flatten), Nil) + case Apply(TypeApply(fun @ Select(qual, name), targs), args) if fun.isTyped => // not trigge + + vprintln("[checker] checking select apply type-apply " + tree + "/" + tpe) + + transChildrenInOrder(tree, tpe, qual::(transArgList(fun, args).flatten), Nil) + case TypeApply(fun @ Select(qual, name), args) if fun.isTyped => def stripNullaryMethodType(tp: Type) = tp match { case NullaryMethodType(restpe) => restpe case tp => tp } - vprintln("[checker] checking select apply " + tree + "/" + tpe) + vprintln("[checker] checking select type-apply " + tree + "/" + tpe) transChildrenInOrder(tree, stripNullaryMethodType(tpe), List(qual, fun), Nil) @@ -373,7 +418,7 @@ abstract class CPSAnnotationChecker extends CPSUtils { case TypeApply(fun, args) => - vprintln("[checker] checking type apply " + tree + "/" + tpe) + vprintln("[checker] checking unknown type apply " + tree + "/" + tpe) transChildrenInOrder(tree, tpe, List(fun), Nil) diff --git a/src/continuations/plugin/scala/tools/selectivecps/CPSUtils.scala b/src/continuations/plugin/scala/tools/selectivecps/CPSUtils.scala index 8bbda5dd05..075009ce5e 100644 --- a/src/continuations/plugin/scala/tools/selectivecps/CPSUtils.scala +++ b/src/continuations/plugin/scala/tools/selectivecps/CPSUtils.scala @@ -12,7 +12,7 @@ trait CPSUtils { var cpsEnabled = true val verbose: Boolean = System.getProperty("cpsVerbose", "false") == "true" def vprintln(x: =>Any): Unit = if (verbose) println(x) - + object cpsNames { val catches = newTermName("$catches") val ex = newTermName("$ex") diff --git a/src/continuations/plugin/scala/tools/selectivecps/SelectiveANFTransform.scala b/src/continuations/plugin/scala/tools/selectivecps/SelectiveANFTransform.scala index cea558d2d3..1189cc2e38 100644 --- a/src/continuations/plugin/scala/tools/selectivecps/SelectiveANFTransform.scala +++ b/src/continuations/plugin/scala/tools/selectivecps/SelectiveANFTransform.scala @@ -47,20 +47,20 @@ abstract class SelectiveANFTransform extends PluginComponent with Transform with // ValDef case here. case dd @ DefDef(mods, name, tparams, vparamss, tpt, rhs) => - log("transforming " + dd.symbol) + debuglog("transforming " + dd.symbol) atOwner(dd.symbol) { val rhs1 = transExpr(rhs, None, getExternalAnswerTypeAnn(tpt.tpe)) - log("result "+rhs1) - log("result is of type "+rhs1.tpe) + debuglog("result "+rhs1) + debuglog("result is of type "+rhs1.tpe) treeCopy.DefDef(dd, mods, name, transformTypeDefs(tparams), transformValDefss(vparamss), transform(tpt), rhs1) } case ff @ Function(vparams, body) => - log("transforming anon function " + ff.symbol) + debuglog("transforming anon function " + ff.symbol) atOwner(ff.symbol) { @@ -88,22 +88,26 @@ abstract class SelectiveANFTransform extends PluginComponent with Transform with transExpr(body, None, ext) } - log("result "+body1) - log("result is of type "+body1.tpe) + debuglog("result "+body1) + debuglog("result is of type "+body1.tpe) treeCopy.Function(ff, transformValDefs(vparams), body1) } case vd @ ValDef(mods, name, tpt, rhs) => // object-level valdefs - log("transforming valdef " + vd.symbol) + debuglog("transforming valdef " + vd.symbol) - atOwner(vd.symbol) { + if (getExternalAnswerTypeAnn(tpt.tpe).isEmpty) { + + atOwner(vd.symbol) { - assert(getExternalAnswerTypeAnn(tpt.tpe) == None) + val rhs1 = transExpr(rhs, None, None) - val rhs1 = transExpr(rhs, None, None) - - treeCopy.ValDef(vd, mods, name, transform(tpt), rhs1) + treeCopy.ValDef(vd, mods, name, transform(tpt), rhs1) + } + } else { + unit.error(tree.pos, "cps annotations not allowed on by-value parameters or value definitions") + super.transform(tree) } case TypeTree() => @@ -298,8 +302,8 @@ abstract class SelectiveANFTransform extends PluginComponent with Transform with if (!expr.isEmpty && (expr.tpe.typeSymbol ne NothingClass)) { // must convert! - log("cps type conversion (has: " + cpsA + "/" + spc + "/" + expr.tpe + ")") - log("cps type conversion (expected: " + cpsR.get + "): " + expr) + debuglog("cps type conversion (has: " + cpsA + "/" + spc + "/" + expr.tpe + ")") + debuglog("cps type conversion (expected: " + cpsR.get + "): " + expr) if (!hasPlusMarker(expr.tpe)) unit.warning(tree.pos, "expression " + tree + " is cps-transformed unexpectedly") @@ -322,10 +326,10 @@ abstract class SelectiveANFTransform extends PluginComponent with Transform with } else if (!cpsR.isDefined && bot.isDefined) { // error! - log("cps type error: " + expr) + debuglog("cps type error: " + expr) //println("cps type error: " + expr + "/" + expr.tpe + "/" + getAnswerTypeAnn(expr.tpe)) - println(cpsR + "/" + spc + "/" + bot) + //println(cpsR + "/" + spc + "/" + bot) unit.error(tree.pos, "found cps expression in non-cps position") } else { diff --git a/src/continuations/plugin/scala/tools/selectivecps/SelectiveCPSTransform.scala b/src/continuations/plugin/scala/tools/selectivecps/SelectiveCPSTransform.scala index b2a1546b4e..6453671eac 100644 --- a/src/continuations/plugin/scala/tools/selectivecps/SelectiveCPSTransform.scala +++ b/src/continuations/plugin/scala/tools/selectivecps/SelectiveCPSTransform.scala @@ -39,10 +39,10 @@ abstract class SelectiveCPSTransform extends PluginComponent with val newtp = transformCPSType(tp) if (newtp != tp) - log("transformInfo changed type for " + sym + " to " + newtp); + debuglog("transformInfo changed type for " + sym + " to " + newtp); if (sym == MethReifyR) - log("transformInfo (not)changed type for " + sym + " to " + newtp); + debuglog("transformInfo (not)changed type for " + sym + " to " + newtp); newtp } @@ -83,13 +83,13 @@ abstract class SelectiveCPSTransform extends PluginComponent with case Apply(TypeApply(fun, targs), args) if (fun.symbol == MethShift) => - log("found shift: " + tree) + debuglog("found shift: " + tree) atPos(tree.pos) { val funR = gen.mkAttributedRef(MethShiftR) // TODO: correct? //gen.mkAttributedSelect(gen.mkAttributedSelect(gen.mkAttributedSelect(gen.mkAttributedIdent(ScalaPackage), //ScalaPackage.tpe.member("util")), ScalaPackage.tpe.member("util").tpe.member("continuations")), MethShiftR) //gen.mkAttributedRef(ModCPS.tpe, MethShiftR) // TODO: correct? - log(funR.tpe) + debuglog("funR.tpe = " + funR.tpe) Apply( TypeApply(funR, targs).setType(appliedType(funR.tpe, targs.map((t:Tree) => t.tpe))), args.map(transform(_)) @@ -98,10 +98,10 @@ abstract class SelectiveCPSTransform extends PluginComponent with case Apply(TypeApply(fun, targs), args) if (fun.symbol == MethShiftUnit) => - log("found shiftUnit: " + tree) + debuglog("found shiftUnit: " + tree) atPos(tree.pos) { val funR = gen.mkAttributedRef(MethShiftUnitR) // TODO: correct? - log(funR.tpe) + debuglog("funR.tpe = " + funR.tpe) Apply( TypeApply(funR, List(targs(0), targs(1))).setType(appliedType(funR.tpe, List(targs(0).tpe, targs(1).tpe))), @@ -114,7 +114,7 @@ abstract class SelectiveCPSTransform extends PluginComponent with log("found reify: " + tree) atPos(tree.pos) { val funR = gen.mkAttributedRef(MethReifyR) // TODO: correct? - log(funR.tpe) + debuglog("funR.tpe = " + funR.tpe) Apply( TypeApply(funR, targs).setType(appliedType(funR.tpe, targs.map((t:Tree) => t.tpe))), args.map(transform(_)) @@ -203,7 +203,7 @@ abstract class SelectiveCPSTransform extends PluginComponent with rhs.changeOwner(currentOwner -> fun.symbol) val exSym = currentOwner.newValueParameter(cpsNames.ex, pos).setInfo(ThrowableClass.tpe) - val catch2 = { localTyper.typedCases(tree, List( + val catch2 = { localTyper.typedCases(List( CaseDef(Bind(exSym, Typed(Ident("_"), TypeTree(ThrowableClass.tpe))), Apply(Select(Ident(funSym), nme.isDefinedAt), List(Ident(exSym))), Apply(Ident(funSym), List(Ident(exSym)))) @@ -258,17 +258,17 @@ abstract class SelectiveCPSTransform extends PluginComponent with case vd @ ValDef(mods, name, tpt, rhs) if (vd.symbol.hasAnnotation(MarkerCPSSym)) => - log("found marked ValDef "+name+" of type " + vd.symbol.tpe) + debuglog("found marked ValDef "+name+" of type " + vd.symbol.tpe) val tpe = vd.symbol.tpe val rhs1 = atOwner(vd.symbol) { transform(rhs) } rhs1.changeOwner(vd.symbol -> currentOwner) // TODO: don't traverse twice - log("valdef symbol " + vd.symbol + " has type " + tpe) - log("right hand side " + rhs1 + " has type " + rhs1.tpe) + debuglog("valdef symbol " + vd.symbol + " has type " + tpe) + debuglog("right hand side " + rhs1 + " has type " + rhs1.tpe) - log("currentOwner: " + currentOwner) - log("currentMethod: " + currentMethod) + debuglog("currentOwner: " + currentOwner) + debuglog("currentMethod: " + currentMethod) val (bodyStms, bodyExpr) = transBlock(rest, expr) // FIXME: result will later be traversed again by TreeSymSubstituter and @@ -308,12 +308,12 @@ abstract class SelectiveCPSTransform extends PluginComponent with // see note about multiple traversals above - log("fun.symbol: "+fun.symbol) - log("fun.symbol.owner: "+fun.symbol.owner) - log("arg.owner: "+arg.owner) + debuglog("fun.symbol: "+fun.symbol) + debuglog("fun.symbol.owner: "+fun.symbol.owner) + debuglog("arg.owner: "+arg.owner) - log("fun.tpe:"+fun.tpe) - log("return type of fun:"+body1.tpe) + debuglog("fun.tpe:"+fun.tpe) + debuglog("return type of fun:"+body1.tpe) var methodName = nme.map @@ -324,7 +324,7 @@ abstract class SelectiveCPSTransform extends PluginComponent with else unit.error(rhs.pos, "cannot compute type for CPS-transformed function result") - log("will use method:"+methodName) + debuglog("will use method:"+methodName) localTyper.typed(atPos(vd.symbol.pos) { Apply(Select(ctxR, ctxR.tpe.member(methodName)), List(fun)) @@ -335,7 +335,7 @@ abstract class SelectiveCPSTransform extends PluginComponent with try { if (specialCaseTrivial) { - log("will optimize possible tail call: " + bodyExpr) + debuglog("will optimize possible tail call: " + bodyExpr) // FIXME: flatMap impl has become more complicated due to // exceptions. do we need to put a try/catch in the then part?? |