From 3c8196300d65738d6779ba8703e2a86ee3390ec7 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sat, 28 Dec 2013 21:46:05 +0100 Subject: New version of eta-expansion. This version expands a method ref p.m to the untyped tree p.m(_, ..., _) (after lifting impure expressions from p). Afterwards the usual application mechanisms kick in. This fixes problems also present in Scala 2.x, where an eta-expanded function was not as flexible as an explicitly expanded one (for instance, eta expansion did not honor default parameters). --- src/dotty/tools/dotc/typer/EtaExpansion.scala | 36 +++++++++++++-------------- 1 file changed, 17 insertions(+), 19 deletions(-) (limited to 'src/dotty/tools/dotc/typer/EtaExpansion.scala') diff --git a/src/dotty/tools/dotc/typer/EtaExpansion.scala b/src/dotty/tools/dotc/typer/EtaExpansion.scala index 16a02ba5c..46a1d3583 100644 --- a/src/dotty/tools/dotc/typer/EtaExpansion.scala +++ b/src/dotty/tools/dotc/typer/EtaExpansion.scala @@ -94,33 +94,31 @@ object EtaExpansion { } /** Eta-expanding a tree means converting a method reference to a function value. - * @param tree The tree to expand - * @param wtp The widened type of the tree, which is always a MethodType - * Let `wtp` be the method type - * - * (x1: T1, ..., xn: Tn): R - * + * @param tree The tree to expand + * @param paramNames The names of the parameters to use in the expansion + * Let `paramNames` be x1, ..., xn * and assume the lifted application of `tree` (@see liftApp) is * * { val xs = es; expr } * * Then the eta-expansion is * - * { val xs = es; - * { def $anonfun(x1: T1, ..., xn: Tn): T = expr; Closure($anonfun) }} + * { val xs = es; (x1, ..., xn) => expr(xx1, ..., xn) } + * + * This is an untyped tree, with `es` and `expr` as typed splices. */ - def etaExpand(tree: Tree, tpe: MethodType)(implicit ctx: Context): Tree = { - def expand(lifted: Tree): Tree = { - val meth = ctx.newSymbol(ctx.owner, nme.ANON_FUN, Synthetic, tpe, coord = tree.pos) - Closure(meth, argss => (lifted /: argss)(Apply(_, _))) - } - val defs = new mutable.ListBuffer[Tree] - val lifted = liftApp(defs, tree) - wrapDefs(defs, expand(lifted)) + def etaExpand(tree: Tree, paramNames: List[TermName])(implicit ctx: Context): untpd.Tree = { + import untpd._ + val defs = new mutable.ListBuffer[tpd.Tree] + val lifted: Tree = TypedSplice(liftApp(defs, tree)) + val params = paramNames map (name => + ValDef(Modifiers(Synthetic | Param), name, TypeTree(), EmptyTree).withPos(tree.pos)) + val ids = paramNames map (name => + Ident(name).withPos(tree.pos)) + val body = Apply(lifted, ids) + val fn = untpd.Function(params, body) + if (defs.nonEmpty) untpd.Block(defs.toList map untpd.TypedSplice, fn) else fn } - - def wrapDefs(defs: mutable.ListBuffer[Tree], tree: Tree)(implicit ctx: Context): Tree = - if (defs != null && defs.nonEmpty) tpd.Block(defs.toList, tree) else tree } /**

not needed -- cgit v1.2.3