Skip to content
Browse files

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.
  • Loading branch information...
1 parent a1da835 commit d7d63e93f35c692b26e95db1b02d758723dde18d @retronym retronym committed with adriaanm Nov 10, 2013
View
62 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,59 +270,37 @@ 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.
methDef.tpt setType localTyper.packedType(body, methSym).deconst
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)))
}
}
}
View
6 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 --------------------------------------------------------

0 comments on commit d7d63e9

Please sign in to comment.
Something went wrong with that request. Please try again.