@@ -32,8 +32,6 @@ private[async] final case class TransformUtils[C <: Context](c: C) {
3232 val await = " await"
3333 val bindSuffix = " $bind"
3434
35- def arg (i : Int ) = " arg" + i
36-
3735 def fresh (name : TermName ): TermName = newTermName(fresh(name.toString))
3836
3937 def fresh (name : String ): String = if (name.toString.contains(" $" )) name else c.fresh(" " + name + " $" )
@@ -102,11 +100,13 @@ private[async] final case class TransformUtils[C <: Context](c: C) {
102100 case dd : DefDef => nestedMethod(dd)
103101 case fun : Function => function(fun)
104102 case m@ Match (EmptyTree , _) => patMatFunction(m) // Pattern matching anonymous function under -Xoldpatmat of after `restorePatternMatchingFunctions`
105- case Apply (fun, args) =>
103+ case Applied (fun, targs, argss) if argss.nonEmpty =>
106104 val isInByName = isByName(fun)
107- for ((arg, index) <- args.zipWithIndex) {
108- if (! isInByName(index)) traverse(arg)
109- else byNameArgument(arg)
105+ for ((args, i) <- argss.zipWithIndex) {
106+ for ((arg, j) <- args.zipWithIndex) {
107+ if (! isInByName(i, j)) traverse(arg)
108+ else byNameArgument(arg)
109+ }
110110 }
111111 traverse(fun)
112112 case _ => super .traverse(tree)
@@ -122,13 +122,31 @@ private[async] final case class TransformUtils[C <: Context](c: C) {
122122 Set (Boolean_&& , Boolean_|| )
123123 }
124124
125- def isByName (fun : Tree ): (Int => Boolean ) = {
126- if (Boolean_ShortCircuits contains fun.symbol) i => true
127- else fun.tpe match {
128- case MethodType (params, _) =>
129- val isByNameParams = params.map(_.asTerm.isByNameParam)
130- (i : Int ) => isByNameParams.applyOrElse(i, (_ : Int ) => false )
131- case _ => Map ()
125+ def isByName (fun : Tree ): ((Int , Int ) => Boolean ) = {
126+ if (Boolean_ShortCircuits contains fun.symbol) (i, j) => true
127+ else {
128+ val symtab = c.universe.asInstanceOf [reflect.internal.SymbolTable ]
129+ val paramss = fun.tpe.asInstanceOf [symtab.Type ].paramss
130+ val byNamess = paramss.map(_.map(_.isByNameParam))
131+ (i, j) => util.Try (byNamess(i)(j)).getOrElse(false )
132+ }
133+ }
134+ def argName (fun : Tree ): ((Int , Int ) => String ) = {
135+ val symtab = c.universe.asInstanceOf [reflect.internal.SymbolTable ]
136+ val paramss = fun.tpe.asInstanceOf [symtab.Type ].paramss
137+ val namess = paramss.map(_.map(_.name.toString))
138+ (i, j) => util.Try (namess(i)(j)).getOrElse(s " arg_ ${i}_ ${j}" )
139+ }
140+
141+ object Applied {
142+ val symtab = c.universe.asInstanceOf [scala.reflect.internal.SymbolTable ]
143+ object treeInfo extends {
144+ val global : symtab.type = symtab
145+ } with reflect.internal.TreeInfo
146+
147+ def unapply (tree : Tree ): Some [(Tree , List [Tree ], List [List [Tree ]])] = {
148+ val treeInfo .Applied (core, targs, argss) = tree.asInstanceOf [symtab.Tree ]
149+ Some ((core.asInstanceOf [Tree ], targs.asInstanceOf [List [Tree ]], argss.asInstanceOf [List [List [Tree ]]]))
132150 }
133151 }
134152
@@ -301,7 +319,6 @@ private[async] final case class TransformUtils[C <: Context](c: C) {
301319 }
302320 }
303321
304-
305322 def isSafeToInline (tree : Tree ) = {
306323 val symtab = c.universe.asInstanceOf [scala.reflect.internal.SymbolTable ]
307324 object treeInfo extends {
@@ -321,7 +338,7 @@ private[async] final case class TransformUtils[C <: Context](c: C) {
321338 * @param f A function from argument (with '_*' unwrapped) and argument index to argument.
322339 * @tparam A The type of the auxillary result
323340 */
324- def mapArguments [A ](args : List [Tree ])(f : (Tree , Int ) => (A , Tree )): (List [A ], List [Tree ]) = {
341+ private def mapArguments [A ](args : List [Tree ])(f : (Tree , Int ) => (A , Tree )): (List [A ], List [Tree ]) = {
325342 args match {
326343 case args :+ Typed (tree, Ident (tpnme.WILDCARD_STAR )) =>
327344 val (a, argExprs :+ lastArgExpr) = (args :+ tree).zipWithIndex.map(f.tupled).unzip
@@ -331,4 +348,27 @@ private[async] final case class TransformUtils[C <: Context](c: C) {
331348 args.zipWithIndex.map(f.tupled).unzip
332349 }
333350 }
351+
352+ case class Arg (expr : Tree , isByName : Boolean , argName : String )
353+
354+ /**
355+ * Transform a list of argument lists, producing the transformed lists, and lists of auxillary
356+ * results.
357+ *
358+ * The function `f` need not concern itself with varargs arguments e.g (`xs : _*`). It will
359+ * receive `xs`, and it's result will be re-wrapped as `f(xs) : _*`.
360+ *
361+ * @param fun The function being applied
362+ * @param argss The argument lists
363+ * @return (auxillary results, mapped argument trees)
364+ */
365+ def mapArgumentss [A ](fun : Tree , argss : List [List [Tree ]])(f : Arg => (A , Tree )): (List [List [A ]], List [List [Tree ]]) = {
366+ val isByNamess : (Int , Int ) => Boolean = isByName(fun)
367+ val argNamess : (Int , Int ) => String = argName(fun)
368+ argss.zipWithIndex.map { case (args, i) =>
369+ mapArguments[A ](args) {
370+ (tree, j) => f(Arg (tree, isByNamess(i, j), argNamess(i, j)))
371+ }
372+ }.unzip
373+ }
334374}
0 commit comments