summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Zaugg <jzaugg@gmail.com>2013-11-10 13:40:26 +0100
committerAdriaan Moors <adriaan.moors@typesafe.com>2013-11-17 14:58:18 -0800
commitd7d63e93f35c692b26e95db1b02d758723dde18d (patch)
tree4db075cbf865e55477bd2fb80e0c727ff759c832
parenta1da835da62114d76b165125a940bfb86c417716 (diff)
downloadscala-d7d63e93f35c692b26e95db1b02d758723dde18d.tar.gz
scala-d7d63e93f35c692b26e95db1b02d758723dde18d.tar.bz2
scala-d7d63e93f35c692b26e95db1b02d758723dde18d.zip
Tidy up the Uncurry component of delambdafy
- Use tree factories that accept symbols and encapsulate ValDef creation - Use `gen.mkForwarder` to handle the conditional addition of `: _*` for varargs functions. We don't need to predicate this on `etaExpandKeepsStar`; the only place that need to do that is EtaExpansion.
-rw-r--r--src/compiler/scala/tools/nsc/transform/UnCurry.scala62
-rw-r--r--src/reflect/scala/reflect/internal/Trees.scala6
2 files changed, 26 insertions, 42 deletions
diff --git a/src/compiler/scala/tools/nsc/transform/UnCurry.scala b/src/compiler/scala/tools/nsc/transform/UnCurry.scala
index 3d648ccbac..d1d4759ea5 100644
--- a/src/compiler/scala/tools/nsc/transform/UnCurry.scala
+++ b/src/compiler/scala/tools/nsc/transform/UnCurry.scala
@@ -217,14 +217,14 @@ abstract class UnCurry extends InfoTransform
// nullary or parameterless
case fun1 if fun1 ne fun => fun1
case _ =>
- val parents = addSerializable(abstractFunctionForFunctionType(fun.tpe))
- val anonClass = fun.symbol.owner newAnonymousFunctionClass(fun.pos, inConstructorFlag) addAnnotation SerialVersionUIDAnnotation
- anonClass setInfo ClassInfoType(parents, newScope, anonClass)
+ val formals :+ restpe = fun.tpe.typeArgs
- val targs = fun.tpe.typeArgs
- val (formals, restpe) = (targs.init, targs.last)
+ def typedFunPos(t: Tree) = localTyper.typedPos(fun.pos)(t)
if (inlineFunctionExpansion) {
+ val parents = addSerializable(abstractFunctionForFunctionType(fun.tpe))
+ val anonClass = fun.symbol.owner newAnonymousFunctionClass(fun.pos, inConstructorFlag) addAnnotation SerialVersionUIDAnnotation
+ anonClass setInfo ClassInfoType(parents, newScope, anonClass)
val applyMethodDef = {
val methSym = anonClass.newMethod(nme.apply, fun.pos, FINAL)
val paramSyms = map2(formals, fun.vparams) {
@@ -235,7 +235,7 @@ abstract class UnCurry extends InfoTransform
fun.vparams foreach (_.symbol.owner = methSym)
fun.body changeOwner (fun.symbol -> methSym)
- val body = localTyper.typedPos(fun.pos)(fun.body)
+ val body = typedFunPos(fun.body)
val methDef = DefDef(methSym, List(fun.vparams), body)
// Have to repack the type to avoid mismatches when existentials
@@ -244,7 +244,7 @@ abstract class UnCurry extends InfoTransform
methDef
}
- localTyper.typedPos(fun.pos) {
+ typedFunPos {
Block(
List(ClassDef(anonClass, NoMods, ListOfNil, List(applyMethodDef), fun.pos)),
Typed(New(anonClass.tpe), TypeTree(fun.tpe)))
@@ -270,23 +270,17 @@ abstract class UnCurry extends InfoTransform
* @bodyF function that turns the method symbol and list of value params
* into a body for the method
*/
- def createMethod(owner: Symbol, name: TermName, additionalFlags: Long)(bodyF: (Symbol, List[ValDef]) => Tree) = {
+ def createMethod(owner: Symbol, name: TermName, additionalFlags: Long)(bodyF: Symbol => Tree) = {
val methSym = owner.newMethod(name, fun.pos, FINAL | additionalFlags)
- val vparams = fun.vparams map (_.duplicate)
- val paramSyms = map2(formals, vparams) {
+ val paramSyms = map2(formals, fun.vparams) {
(tp, vparam) => methSym.newSyntheticValueParam(tp, vparam.name)
}
- foreach2(vparams, paramSyms){(valdef, sym) => valdef.symbol = sym}
- vparams foreach (_.symbol.owner = methSym)
- val methodType = MethodType(paramSyms, restpe.deconst)
- methSym setInfo methodType
+ methSym setInfo MethodType(paramSyms, restpe.deconst)
- // TODO this is probably cleaner if bodyF only works with symbols rather than parameter ValDefs
- val tempBody = bodyF(methSym, vparams)
- val body = localTyper.typedPos(fun.pos)(tempBody)
- val methDef = DefDef(methSym, List(vparams), body)
+ val body = typedFunPos(bodyF(methSym))
+ val methDef = DefDef(methSym, body)
// Have to repack the type to avoid mismatches when existentials
// appear in the result - see SI-4869.
@@ -294,35 +288,19 @@ abstract class UnCurry extends InfoTransform
methDef
}
- val methodFlags = ARTIFACT
+ val funParams = fun.vparams map (_.symbol)
// method definition with the same arguments, return type, and body as the original lambda
- val liftedMethod = createMethod(fun.symbol.owner, tpnme.ANON_FUN_NAME.toTermName, methodFlags){
- case(methSym, vparams) =>
- fun.body.substituteSymbols(fun.vparams map (_.symbol), vparams map (_.symbol))
+ val liftedMethod = createMethod(fun.symbol.owner, nme.ANON_FUN_NAME, additionalFlags = ARTIFACT) {
+ methSym =>
+ fun.body.substituteSymbols(funParams, methSym.paramss.head)
fun.body changeOwner (fun.symbol -> methSym)
}
- // callsite for the lifted method
- val args = fun.vparams map { vparam =>
- val ident = Ident(vparam.symbol)
- // if -Yeta-expand-keeps-star is turned on then T* types can get through. In order
- // to forward them we need to forward x: T* ascribed as "x:_*"
- if (settings.etaExpandKeepsStar && definitions.isRepeatedParamType(vparam.tpt.tpe))
- gen.wildcardStar(ident)
- else
- ident
- }
-
- val funTyper = localTyper.typedPos(fun.pos) _
-
- val liftedMethodCall = funTyper(Apply(liftedMethod.symbol, args:_*))
-
// new function whose body is just a call to the lifted method
- val newFun = treeCopy.Function(fun, fun.vparams, liftedMethodCall)
- funTyper(Block(
- List(funTyper(liftedMethod)),
- super.transform(newFun)
- ))
+ val newFun = deriveFunction(fun)(_ => typedFunPos(
+ gen.mkForwarder(gen.mkAttributedRef(liftedMethod.symbol), funParams :: Nil)
+ ))
+ typedFunPos(Block(liftedMethod, super.transform(newFun)))
}
}
}
diff --git a/src/reflect/scala/reflect/internal/Trees.scala b/src/reflect/scala/reflect/internal/Trees.scala
index af0af8afe8..b0abc0be7b 100644
--- a/src/reflect/scala/reflect/internal/Trees.scala
+++ b/src/reflect/scala/reflect/internal/Trees.scala
@@ -1804,6 +1804,12 @@ trait Trees extends api.Trees {
case t =>
sys.error("Not a LabelDef: " + t + "/" + t.getClass)
}
+ def deriveFunction(func: Tree)(applyToRhs: Tree => Tree): Function = func match {
+ case Function(params0, rhs0) =>
+ treeCopy.Function(func, params0, applyToRhs(rhs0))
+ case t =>
+ sys.error("Not a Function: " + t + "/" + t.getClass)
+ }
// -------------- Classtags --------------------------------------------------------