Skip to content

Instantly share code, notes, and snippets.

@ktoso
Last active December 12, 2015 08:58
Show Gist options
  • Save ktoso/4747627 to your computer and use it in GitHub Desktop.
Save ktoso/4747627 to your computer and use it in GitHub Desktop.
import language.experimental.macros // enable the macros language feature
import reflect.macros._
object Alias {
def aliasFor[P1, P2, T](delegate: (P1, P2) => T): T = macro alias_impl[T]
// ...
}
def alias_impl[T](c: Context)(delegate: c.Expr[Any]): c.Expr[T] = {
import c._
val tree = delegate.tree.children match {
case expr :: Nil =>
val methodName = extractDelegateMethodName(c)
val params = extractDelegatorParams(c).mkString(", ")
parse(s"""$methodName($params)""") // : c.Tree
case _ =>
c.abort(c.enclosingPosition, "alias macro should only be used on single method delegation")
}
c.Expr(tree)
}
private def extractDelegateMethodName(c: Context)(children: List[c.universe.Tree]): c.universe.Tree =
children
.map(a => a.children)
.flatten
.filter(_.isTerm) // PS: yeap I know this is getting ugly/long
.filterNot(a => a.isEmpty && a.toString == "aliasFor") // exclude the macro name
.head // first tree inside our macro
.children.head // the thing inside is partially applied - it should be just one method
import pl.project13.scala.macros.Alias.aliasFor
def !!(a: String, b: Int) = aliasFor { manyParams _ }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment