diff options
author | Dmitry Petrashko <dmitry.petrashko@gmail.com> | 2015-04-20 13:50:52 +0200 |
---|---|---|
committer | Dmitry Petrashko <dmitry.petrashko@gmail.com> | 2015-04-20 13:50:52 +0200 |
commit | bacc9f0272b4e95467e8558e174b4ffc8e907e28 (patch) | |
tree | 37b5c1f47d2d170e320ef02d5b326a14d4a42d91 /src/dotty/tools/dotc/transform/FunctionalInterfaces.scala | |
parent | 6dfeaa26c93e8110a54c6e2f6ebf6480dfc74257 (diff) | |
download | dotty-bacc9f0272b4e95467e8558e174b4ffc8e907e28.tar.gz dotty-bacc9f0272b4e95467e8558e174b4ffc8e907e28.tar.bz2 dotty-bacc9f0272b4e95467e8558e174b4ffc8e907e28.zip |
New phase: FunctionalInterfaces.
Rewires closures to implement more specific types of Function SAMs.
Diffstat (limited to 'src/dotty/tools/dotc/transform/FunctionalInterfaces.scala')
-rw-r--r-- | src/dotty/tools/dotc/transform/FunctionalInterfaces.scala | 63 |
1 files changed, 63 insertions, 0 deletions
diff --git a/src/dotty/tools/dotc/transform/FunctionalInterfaces.scala b/src/dotty/tools/dotc/transform/FunctionalInterfaces.scala new file mode 100644 index 000000000..71be682ec --- /dev/null +++ b/src/dotty/tools/dotc/transform/FunctionalInterfaces.scala @@ -0,0 +1,63 @@ +package dotty.tools.dotc +package transform + +import TreeTransforms._ +import core.DenotTransformers._ +import core.Symbols._ +import core.Contexts._ +import core.Types._ +import core.Flags._ +import core.Decorators._ +import core.SymDenotations._ +import core.StdNames.nme +import core.Names._ +import core.NameOps._ +import ast.Trees._ +import SymUtils._ +import dotty.tools.dotc.ast.tpd +import collection.{ mutable, immutable } +import collection.mutable.{ LinkedHashMap, LinkedHashSet, TreeSet } + +/** + * Rewires closures to implement more specific types of Functions. + */ +class FunctionalInterfaces extends MiniPhaseTransform { + import tpd._ + + def phaseName: String = "functionalInterfaces" + + var allowedReturnTypes: Set[Symbol] = _ // moved here to make it explicit what specializations are generated + var allowedArgumentTypes: Set[Symbol] = _ + val maxArgsCount = 2 + + def shouldSpecialize(m: MethodType)(implicit ctx: Context) = + (m.paramTypes.size <= maxArgsCount) && + m.paramTypes.forall(x => allowedArgumentTypes.contains(x.typeSymbol)) && + allowedReturnTypes.contains(m.resultType.typeSymbol) + + val functionName = "JFunction".toTermName + val functionPackage = "scala.compat.java8.".toTermName + + override def prepareForUnit(tree: tpd.Tree)(implicit ctx: Context): TreeTransform = { + allowedReturnTypes = defn.ScalaNumericValueClasses + allowedArgumentTypes = defn.ScalaNumericValueClasses + defn.BooleanClass + this + } + + override def transformClosure(tree: Closure)(implicit ctx: Context, info: TransformerInfo): Tree = { + tree.tpt match { + case EmptyTree => + val m = tree.meth.tpe.widen.asInstanceOf[MethodType] + + if (shouldSpecialize(m)) { + val interfaceName = (functionName ++ m.paramTypes.length.toString).specializedFor(m.resultType, m.paramTypes) + // symbols loaded from classpath aren't defined in periods earlier than when they where loaded + val interface = ctx.requiredClass(functionPackage ++ interfaceName) + val tpt = tpd.TypeTree(interface.asType.typeRef) + tpd.Closure(tree.env, tree.meth, tpt) + } else tree + case _ => + tree + } + } +} |