diff options
Diffstat (limited to 'src/continuations/plugin')
5 files changed, 44 insertions, 56 deletions
diff --git a/src/continuations/plugin/scala/tools/selectivecps/CPSAnnotationChecker.scala b/src/continuations/plugin/scala/tools/selectivecps/CPSAnnotationChecker.scala index 00c72cf423..beab271a3b 100644 --- a/src/continuations/plugin/scala/tools/selectivecps/CPSAnnotationChecker.scala +++ b/src/continuations/plugin/scala/tools/selectivecps/CPSAnnotationChecker.scala @@ -2,11 +2,10 @@ package scala.tools.selectivecps -import scala.tools.nsc.Global -import scala.tools.nsc.typechecker.Modes +import scala.tools.nsc.{ Global, Mode } import scala.tools.nsc.MissingRequirementError -abstract class CPSAnnotationChecker extends CPSUtils with Modes { +abstract class CPSAnnotationChecker extends CPSUtils { val global: Global import global._ import analyzer.{AnalyzerPlugin, Typer} @@ -97,7 +96,7 @@ abstract class CPSAnnotationChecker extends CPSUtils with Modes { if (!cpsEnabled) return bounds val anyAtCPS = newCpsParamsMarker(NothingClass.tpe, AnyClass.tpe) - if (isFunctionType(tparams.head.owner.tpe) || isPartialFunctionType(tparams.head.owner.tpe)) { + if (isFunctionType(tparams.head.owner.tpe_*) || isPartialFunctionType(tparams.head.owner.tpe_*)) { vprintln("function bound: " + tparams.head.owner.tpe + "/"+bounds+"/"+targs) if (hasCpsParamTypes(targs.last)) bounds.reverse match { @@ -123,14 +122,14 @@ abstract class CPSAnnotationChecker extends CPSUtils with Modes { import checker._ - override def canAdaptAnnotations(tree: Tree, typer: Typer, mode: Int, pt: Type): Boolean = { + override def canAdaptAnnotations(tree: Tree, typer: Typer, mode: Mode, pt: Type): Boolean = { if (!cpsEnabled) return false - vprintln("can adapt annotations? " + tree + " / " + tree.tpe + " / " + Integer.toHexString(mode) + " / " + pt) + vprintln("can adapt annotations? " + tree + " / " + tree.tpe + " / " + mode + " / " + pt) val annots1 = cpsParamAnnotation(tree.tpe) val annots2 = cpsParamAnnotation(pt) - if ((mode & global.analyzer.PATTERNmode) != 0) { + if (mode.inPatternMode) { //println("can adapt pattern annotations? " + tree + " / " + tree.tpe + " / " + Integer.toHexString(mode) + " / " + pt) if (!annots1.isEmpty) { return true @@ -139,7 +138,7 @@ abstract class CPSAnnotationChecker extends CPSUtils with Modes { /* // not precise enough -- still relying on addAnnotations to remove things from ValDef symbols - if ((mode & global.analyzer.TYPEmode) != 0 && (mode & global.analyzer.BYVALmode) != 0) { + if ((mode & TYPEmode) != 0 && (mode & BYVALmode) != 0) { if (!annots1.isEmpty) { return true } @@ -148,16 +147,16 @@ abstract class CPSAnnotationChecker extends CPSUtils with Modes { /* this interferes with overloading resolution - if ((mode & global.analyzer.BYVALmode) != 0 && tree.tpe <:< pt) { + if ((mode & BYVALmode) != 0 && tree.tpe <:< pt) { vprintln("already compatible, can't adapt further") return false } */ - if ((mode & global.analyzer.EXPRmode) != 0) { + if (mode.inExprMode) { if ((annots1 corresponds annots2)(_.atp <:< _.atp)) { vprintln("already same, can't adapt further") false - } else if (annots1.isEmpty && !annots2.isEmpty && ((mode & global.analyzer.BYVALmode) == 0)) { + } else if (annots1.isEmpty && !annots2.isEmpty && !mode.inByValMode) { //println("can adapt annotations? " + tree + " / " + tree.tpe + " / " + Integer.toHexString(mode) + " / " + pt) if (!hasPlusMarker(tree.tpe)) { // val base = tree.tpe <:< removeAllCPSAnnotations(pt) @@ -170,10 +169,10 @@ abstract class CPSAnnotationChecker extends CPSUtils with Modes { true //} } else false - } else if (!hasPlusMarker(tree.tpe) && annots1.isEmpty && !annots2.isEmpty && ((mode & global.analyzer.RETmode) != 0)) { + } else if (!hasPlusMarker(tree.tpe) && annots1.isEmpty && !annots2.isEmpty && mode.inRetMode) { vprintln("checking enclosing method's result type without annotations") tree.tpe <:< pt.withoutAnnotations - } else if (!hasMinusMarker(tree.tpe) && !annots1.isEmpty && ((mode & global.analyzer.BYVALmode) != 0)) { + } else if (!hasMinusMarker(tree.tpe) && !annots1.isEmpty && mode.inByValMode) { val optCpsTypes: Option[(Type, Type)] = cpsParamTypes(tree.tpe) val optExpectedCpsTypes: Option[(Type, Type)] = cpsParamTypes(pt) if (optCpsTypes.isEmpty || optExpectedCpsTypes.isEmpty) { @@ -189,21 +188,21 @@ abstract class CPSAnnotationChecker extends CPSUtils with Modes { } else false } - override def adaptAnnotations(tree: Tree, typer: Typer, mode: Int, pt: Type): Tree = { + override def adaptAnnotations(tree: Tree, typer: Typer, mode: Mode, pt: Type): Tree = { if (!cpsEnabled) return tree - vprintln("adapt annotations " + tree + " / " + tree.tpe + " / " + modeString(mode) + " / " + pt) + vprintln("adapt annotations " + tree + " / " + tree.tpe + " / " + mode + " / " + pt) - val patMode = (mode & global.analyzer.PATTERNmode) != 0 - val exprMode = (mode & global.analyzer.EXPRmode) != 0 - val byValMode = (mode & global.analyzer.BYVALmode) != 0 - val retMode = (mode & global.analyzer.RETmode) != 0 + val patMode = mode.inPatternMode + val exprMode = mode.inExprMode + val byValMode = mode.inByValMode + val retMode = mode.inRetMode val annotsTree = cpsParamAnnotation(tree.tpe) val annotsExpected = cpsParamAnnotation(pt) // not sure I rephrased this comment correctly: - // replacing `patMode` in the condition below by `patMode || ((mode & global.analyzer.TYPEmode) != 0 && (mode & global.analyzer.BYVALmode))` + // replacing `patMode` in the condition below by `patMode || ((mode & TYPEmode) != 0 && (mode & BYVALmode))` // doesn't work correctly -- still relying on addAnnotations to remove things from ValDef symbols if (patMode && !annotsTree.isEmpty) tree modifyType removeAllCPSAnnotations else if (exprMode && !byValMode && !hasPlusMarker(tree.tpe) && annotsTree.isEmpty && annotsExpected.nonEmpty) { // shiftUnit @@ -227,7 +226,7 @@ abstract class CPSAnnotationChecker extends CPSUtils with Modes { } else if (retMode && !hasPlusMarker(tree.tpe) && annotsTree.isEmpty && annotsExpected.nonEmpty) { // add a marker annotation that will make tree.tpe behave as pt, subtyping wise // tree will look like having any possible annotation - + // note 1: we are only adding a plus marker if the method's result type is a cps type // (annotsExpected.nonEmpty == cpsParamAnnotation(pt).nonEmpty) // note 2: we are not adding the expected cps annotations, since they will be added @@ -240,7 +239,7 @@ abstract class CPSAnnotationChecker extends CPSUtils with Modes { /** Returns an adapted type for a return expression if the method's result type (pt) is a CPS type. * Otherwise, it returns the `default` type (`typedReturn` passes `NothingClass.tpe`). - * + * * A return expression in a method that has a CPS result type is an error unless the return * is in tail position. Therefore, we are making sure that only the types of return expressions * are adapted which will either be removed, or lead to an error. @@ -363,7 +362,7 @@ abstract class CPSAnnotationChecker extends CPSUtils with Modes { 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]) = { @@ -400,11 +399,13 @@ abstract class CPSAnnotationChecker extends CPSUtils with Modes { /** Modify the type that has thus far been inferred * for a tree. All this should do is add annotations. */ - override def pluginsTyped(tpe: Type, typer: Typer, tree: Tree, mode: Int, pt: Type): Type = { + override def pluginsTyped(tpe: Type, typer: Typer, tree: Tree, mode: Mode, pt: Type): Type = { import scala.util.control._ if (!cpsEnabled) { - if (Exception.failAsValue(classOf[MissingRequirementError])(false)(hasCpsParamTypes(tpe))) + val report = try hasCpsParamTypes(tpe) catch { case _: MissingRequirementError => false } + if (report) global.reporter.error(tree.pos, "this code must be compiled with the Scala continuations plugin enabled") + return tpe } diff --git a/src/continuations/plugin/scala/tools/selectivecps/CPSUtils.scala b/src/continuations/plugin/scala/tools/selectivecps/CPSUtils.scala index 46c644bcd6..29480576ea 100644 --- a/src/continuations/plugin/scala/tools/selectivecps/CPSUtils.scala +++ b/src/continuations/plugin/scala/tools/selectivecps/CPSUtils.scala @@ -7,7 +7,6 @@ import scala.tools.nsc.Global trait CPSUtils { val global: Global import global._ - import definitions._ var cpsEnabled = false val verbose: Boolean = System.getProperty("cpsVerbose", "false") == "true" @@ -36,7 +35,7 @@ trait CPSUtils { lazy val MarkerCPSAdaptMinus = rootMirror.getRequiredClass("scala.util.continuations.cpsMinus") lazy val Context = rootMirror.getRequiredClass("scala.util.continuations.ControlContext") - lazy val ModCPS = rootMirror.getRequiredPackage("scala.util.continuations") + lazy val ModCPS = rootMirror.getPackage("scala.util.continuations") lazy val MethShiftUnit = definitions.getMember(ModCPS, cpsNames.shiftUnit) lazy val MethShiftUnit0 = definitions.getMember(ModCPS, cpsNames.shiftUnit0) @@ -57,12 +56,12 @@ trait CPSUtils { protected def newMarker(sym: Symbol): AnnotationInfo = AnnotationInfo marker sym.tpe protected def newCpsParamsMarker(tp1: Type, tp2: Type) = - newMarker(appliedType(MarkerCPSTypes.tpe, List(tp1, tp2))) + newMarker(appliedType(MarkerCPSTypes, tp1, tp2)) // annotation checker protected def annTypes(ann: AnnotationInfo): (Type, Type) = { - val tp0 :: tp1 :: Nil = ann.atp.normalize.typeArgs + val tp0 :: tp1 :: Nil = ann.atp.dealiasWiden.typeArgs ((tp0, tp1)) } protected def hasMinusMarker(tpe: Type) = tpe hasAnnotation MarkerCPSAdaptMinus diff --git a/src/continuations/plugin/scala/tools/selectivecps/SelectiveANFTransform.scala b/src/continuations/plugin/scala/tools/selectivecps/SelectiveANFTransform.scala index 8b39bf3961..323e894b51 100644 --- a/src/continuations/plugin/scala/tools/selectivecps/SelectiveANFTransform.scala +++ b/src/continuations/plugin/scala/tools/selectivecps/SelectiveANFTransform.scala @@ -2,13 +2,10 @@ package scala.tools.selectivecps -import scala.tools.nsc._ import scala.tools.nsc.transform._ import scala.tools.nsc.symtab._ import scala.tools.nsc.plugins._ -import scala.tools.nsc.ast._ - /** * In methods marked @cps, explicitly name results of calls to other @cps methods */ @@ -20,13 +17,14 @@ abstract class SelectiveANFTransform extends PluginComponent with Transform with import definitions._ // standard classes and methods import typer.atOwner // methods to type trees + override def description = "ANF pre-transform for @cps" + /** the following two members override abstract members in Transform */ val phaseName: String = "selectiveanf" protected def newTransformer(unit: CompilationUnit): Transformer = new ANFTransformer(unit) - class ANFTransformer(unit: CompilationUnit) extends TypingTransformer(unit) { implicit val _unit = unit // allow code in CPSUtils.scala to report errors @@ -131,7 +129,7 @@ abstract class SelectiveANFTransform extends PluginComponent with Transform with def transformPureMatch(tree: Tree, selector: Tree, cases: List[CaseDef]) = { val caseVals = cases map { case cd @ CaseDef(pat, guard, body) => - // if (!hasPlusMarker(body.tpe)) body.tpe = body.tpe withAnnotation newPlusMarker() // TODO: to avoid warning + // if (!hasPlusMarker(body.tpe)) body modifyType (_ withAnnotation newPlusMarker()) // TODO: to avoid warning val bodyVal = transExpr(body, None, ext) // ??? triggers "cps-transformed unexpectedly" warning in transTailValue treeCopy.CaseDef(cd, transform(pat), transform(guard), bodyVal) } @@ -172,7 +170,7 @@ abstract class SelectiveANFTransform extends PluginComponent with Transform with debuglog("transforming valdef " + vd.symbol) if (getExternalAnswerTypeAnn(tpt.tpe).isEmpty) { - + atOwner(vd.symbol) { val rhs1 = transExpr(rhs, None, None) @@ -471,7 +469,7 @@ abstract class SelectiveANFTransform extends PluginComponent with Transform with val sym: Symbol = ( currentOwner.newValue(newTermName(unit.fresh.newName("tmp")), tree.pos, Flags.SYNTHETIC) setInfo valueTpe - setAnnotations List(AnnotationInfo(MarkerCPSSym.tpe, Nil, Nil)) + setAnnotations List(AnnotationInfo(MarkerCPSSym.tpe_*, Nil, Nil)) ) expr.changeOwner(currentOwner -> sym) @@ -503,9 +501,7 @@ abstract class SelectiveANFTransform extends PluginComponent with Transform with // TODO: better yet: do without annotations on symbols val spcVal = getAnswerTypeAnn(anfRhs.tpe) - if (spcVal.isDefined) { - tree.symbol.setAnnotations(List(AnnotationInfo(MarkerCPSSym.tpe, Nil, Nil))) - } + spcVal foreach (_ => tree.symbol setAnnotations List(AnnotationInfo(MarkerCPSSym.tpe_*, Nil, Nil))) (stms:::List(treeCopy.ValDef(tree, mods, name, tpt, anfRhs)), linearize(spc, spcVal)(unit, tree.pos)) diff --git a/src/continuations/plugin/scala/tools/selectivecps/SelectiveCPSPlugin.scala b/src/continuations/plugin/scala/tools/selectivecps/SelectiveCPSPlugin.scala index 237159795a..c16cce2f2c 100644 --- a/src/continuations/plugin/scala/tools/selectivecps/SelectiveCPSPlugin.scala +++ b/src/continuations/plugin/scala/tools/selectivecps/SelectiveCPSPlugin.scala @@ -3,15 +3,11 @@ package scala.tools.selectivecps import scala.tools.nsc -import scala.tools.nsc.typechecker._ import nsc.Global -import nsc.Phase import nsc.plugins.Plugin import nsc.plugins.PluginComponent class SelectiveCPSPlugin(val global: Global) extends Plugin { - import global._ - val name = "continuations" val description = "applies selective cps conversion" @@ -26,7 +22,6 @@ class SelectiveCPSPlugin(val global: Global) extends Plugin { override val runsBefore = List("uncurry") } - val components = List[PluginComponent](anfPhase, cpsPhase) val checker = new CPSAnnotationChecker { diff --git a/src/continuations/plugin/scala/tools/selectivecps/SelectiveCPSTransform.scala b/src/continuations/plugin/scala/tools/selectivecps/SelectiveCPSTransform.scala index 4482bf2b7c..846ce01953 100644 --- a/src/continuations/plugin/scala/tools/selectivecps/SelectiveCPSTransform.scala +++ b/src/continuations/plugin/scala/tools/selectivecps/SelectiveCPSTransform.scala @@ -2,13 +2,8 @@ package scala.tools.selectivecps -import scala.collection._ - -import scala.tools.nsc._ import scala.tools.nsc.transform._ import scala.tools.nsc.plugins._ - -import scala.tools.nsc.ast.TreeBrowsers import scala.tools.nsc.ast._ /** @@ -22,6 +17,8 @@ abstract class SelectiveCPSTransform extends PluginComponent with import definitions._ // standard classes and methods import typer.atOwner // methods to type trees + override def description = "@cps-driven transform of selectiveanf assignments" + /** the following two members override abstract members in Transform */ val phaseName: String = "selectivecps" @@ -56,7 +53,7 @@ abstract class SelectiveCPSTransform extends PluginComponent with case _ => getExternalAnswerTypeAnn(tp) match { case Some((res, outer)) => - appliedType(Context.tpe, List(removeAllCPSAnnotations(tp), res, outer)) + appliedType(Context.tpeHK, List(removeAllCPSAnnotations(tp), res, outer)) case _ => removeAllCPSAnnotations(tp) } @@ -90,7 +87,7 @@ abstract class SelectiveCPSTransform extends PluginComponent with //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? - debuglog("funR.tpe = " + funR.tpe) + debuglog("funR.tpe: " + funR.tpe) Apply( TypeApply(funR, targs).setType(appliedType(funR.tpe, targs.map((t:Tree) => t.tpe))), args.map(transform(_)) @@ -102,12 +99,12 @@ abstract class SelectiveCPSTransform extends PluginComponent with debuglog("found shiftUnit: " + tree) atPos(tree.pos) { val funR = gen.mkAttributedRef(MethShiftUnitR) // TODO: correct? - debuglog("funR.tpe = " + 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))), args.map(transform(_)) - ).setType(appliedType(Context.tpe, List(targs(0).tpe,targs(1).tpe,targs(1).tpe))) + ).setType(appliedType(Context.tpeHK, List(targs(0).tpe,targs(1).tpe,targs(1).tpe))) } case Apply(TypeApply(fun, targs), args) @@ -115,7 +112,7 @@ abstract class SelectiveCPSTransform extends PluginComponent with log("found reify: " + tree) atPos(tree.pos) { val funR = gen.mkAttributedRef(MethReifyR) // TODO: correct? - debuglog("funR.tpe = " + funR.tpe) + debuglog("funR.tpe: " + funR.tpe) Apply( TypeApply(funR, targs).setType(appliedType(funR.tpe, targs.map((t:Tree) => t.tpe))), args.map(transform(_)) @@ -192,7 +189,7 @@ abstract class SelectiveCPSTransform extends PluginComponent with val targettp = transformCPSType(tree.tpe) val pos = catches.head.pos - val funSym = currentOwner.newValueParameter(cpsNames.catches, pos).setInfo(appliedType(PartialFunctionClass.tpe, List(ThrowableClass.tpe, targettp))) + val funSym = currentOwner.newValueParameter(cpsNames.catches, pos).setInfo(appliedType(PartialFunctionClass, ThrowableClass.tpe, targettp)) val funDef = localTyper.typedPos(pos) { ValDef(funSym, Match(EmptyTree, catches1)) } @@ -350,7 +347,7 @@ abstract class SelectiveCPSTransform extends PluginComponent with val ctxSym = currentOwner.newValue(newTermName("" + vd.symbol.name + cpsNames.shiftSuffix)).setInfo(rhs1.tpe) val ctxDef = localTyper.typed(ValDef(ctxSym, rhs1)) def ctxRef = localTyper.typed(Ident(ctxSym)) - val argSym = currentOwner.newValue(vd.symbol.name).setInfo(tpe) + val argSym = currentOwner.newValue(vd.symbol.name.toTermName).setInfo(tpe) val argDef = localTyper.typed(ValDef(argSym, Select(ctxRef, ctxRef.tpe.member(cpsNames.getTrivialValue)))) val switchExpr = localTyper.typedPos(vd.symbol.pos) { val body2 = mkBlock(bodyStms, bodyExpr).duplicate // dup before typing! |