From ad90614c391328bdc9d13795d26f339f67e7f4d5 Mon Sep 17 00:00:00 2001 From: Adriaan Moors Date: Fri, 5 Feb 2016 13:33:39 -0800 Subject: Refactoring. Sweep Sammy's backyard. --- src/compiler/scala/tools/nsc/ast/TreeGen.scala | 46 ++++++++++++++++++-------- 1 file changed, 32 insertions(+), 14 deletions(-) (limited to 'src/compiler/scala/tools/nsc/ast/TreeGen.scala') diff --git a/src/compiler/scala/tools/nsc/ast/TreeGen.scala b/src/compiler/scala/tools/nsc/ast/TreeGen.scala index 7edac76b91..7b0216a6d7 100644 --- a/src/compiler/scala/tools/nsc/ast/TreeGen.scala +++ b/src/compiler/scala/tools/nsc/ast/TreeGen.scala @@ -278,26 +278,44 @@ abstract class TreeGen extends scala.reflect.internal.TreeGen with TreeDSL { * @param additionalFlags flags to be put on the method in addition to FINAL */ def mkMethodFromFunction(localTyper: analyzer.Typer) - (fun: Function, owner: Symbol, name: TermName, additionalFlags: FlagSet = NoFlags) = { - val funParams = fun.vparams map (_.symbol) - val formals :+ restpe = fun.tpe.typeArgs + (owner: Symbol, fun: Function, name: TermName = nme.apply, additionalFlags: FlagSet = NoFlags) = { + val funParamSyms = fun.vparams.map(_.symbol) val methSym = owner.newMethod(name, fun.pos, FINAL | additionalFlags) + val methParamSyms = funParamSyms.map { param => methSym.newSyntheticValueParam(param.tpe, param.name.toTermName) } - val paramSyms = map2(formals, fun.vparams) { - (tp, vparam) => methSym.newSyntheticValueParam(tp, vparam.name) - } + val body = fun.body + body substituteSymbols (funParamSyms, methParamSyms) + body changeOwner ((fun.symbol, methSym)) - methSym setInfo MethodType(paramSyms, restpe.deconst) + // Have to repack the type to avoid mismatches when existentials + // appear in the result - see SI-4869. + val resTp = localTyper.packedType(body, methSym).deconst + methSym setInfo MethodType(methParamSyms, fun.tpe.typeArgs.last.deconst) // TODO: use `resTp` -- preserving wrong status quo because refactoring-only - fun.body.substituteSymbols(funParams, paramSyms) - fun.body changeOwner (fun.symbol -> methSym) + newDefDef(methSym, body)(tpt = TypeTree(resTp)) + } - val methDef = DefDef(methSym, fun.body) + def functionClassType(fun: Function): Type = + abstractFunctionType(fun.vparams.map(_.symbol.tpe), fun.tpe.typeArgs.last.deconst) // TODO: use `fun.body.tpe.deconst` -- preserving wrong status quo because refactoring-only - // Have to repack the type to avoid mismatches when existentials - // appear in the result - see SI-4869. - methDef.tpt setType localTyper.packedType(fun.body, methSym).deconst - methDef + def expandFunction(localTyper: analyzer.Typer)(fun: Function, inConstructorFlag: Long): Tree = { + val parents = addSerializable(functionClassType(fun)) + val anonClass = fun.symbol.owner newAnonymousFunctionClass(fun.pos, inConstructorFlag) addAnnotation SerialVersionUIDAnnotation + + // The original owner is used in the backend for the EnclosingMethod attribute. If fun is + // nested in a value-class method, its owner was already changed to the extension method. + // Saving the original owner allows getting the source structure from the class symbol. + defineOriginalOwner(anonClass, fun.symbol.originalOwner) + anonClass setInfo ClassInfoType(parents, newScope, anonClass) + + val applyMethodDef = mkMethodFromFunction(localTyper)(anonClass, fun) + anonClass.info.decls enter applyMethodDef.symbol + + localTyper.typedPos(fun.pos) { + Block( + ClassDef(anonClass, NoMods, ListOfNil, List(applyMethodDef), fun.pos), + Typed(New(anonClass.tpe), TypeTree(fun.tpe))) + } } } -- cgit v1.2.3