Skip to content

Instantly share code, notes, and snippets.

@wangzaixiang
Created January 19, 2013 09:27
Show Gist options
  • Save wangzaixiang/4571571 to your computer and use it in GitHub Desktop.
Save wangzaixiang/4571571 to your computer and use it in GitHub Desktop.
Scala Macros Usage
package macro_basic
import scala.reflect.macros.Context
import scala.language.experimental.macros
object BeanMacros {
def ToString[A](obj: A): String = macro toStringMacro[A]
def toStringMacro[A](c: Context)(obj: c.Expr[A]): c.Expr[String] = {
import c.universe._
val tpe = obj.actualType
val className = tpe.typeSymbol.name
val declaredGetters = tpe.declarations.filter(_.asTerm.isGetter)
// .+ is actually the method "$plus"
val plus = "$plus"
// start: "ClassName"
val startLit = Literal(Constant(className + "("))
val getterBody = declaredGetters.foldLeft(startLit: TermTree) { (soFar, getSym) =>
// ((((soFar.+(", ")).+(fieldName)).+("=")).+(obj.getter))
val name = Apply(Select(soFar, plus), List(Literal(Constant(getSym.name.toString + "="))))
val namePlusAccess = Apply(Select(name, plus), List(Select(obj.tree, getSym.name)))
// unless last getter, append a ", "
if (getSym != declaredGetters.last) {
Apply(Select(namePlusAccess, plus), List(Literal(Constant(", "))))
} else {
namePlusAccess
}
}
// append end ")"
val body = Apply(Select(getterBody, plus), List(Literal(Constant(")"))))
c.Expr[String](body)
}
}
package macro_basic
import scala.reflect.macros.Context
import scala.language.experimental.macros
object LogMacros {
def print(msg: String) = macro Impls.print
def debug(msg: String) = macro Impls.debug
var isDebugEnabled = false
object Impls {
def print(c: Context)(msg: c.Expr[String]): c.Expr[Any] = {
println("inside macro print")
c.universe.reify {
Console.println("Hello:" + msg.splice)
}
}
def debug(c: Context)(msg: c.Expr[String]) = {
c.universe.reify {
if(isDebugEnabled) Console.println(msg.splice)
}
}
}
}
package macro_basic
import scala.reflect.macros.Context
import scala.language.experimental.macros
object SourceMacros {
def __FUNC__ = macro Impl.__FUNC__Impl
def __LINE__ = macro Impl.__LINE__Impl
def __FILE__ = macro Impl.__FILE__Impl
object Impl {
def __FUNC__Impl(c: Context) = {
c.enclosingMethod match {
case c.universe.DefDef(_, name, _, _, _, _) =>
c.universe.reify(c.literal(name.toString).splice)
case _ => c.abort(c.enclosingPosition, "no enclosing method")
}
}
def __LINE__Impl(c: Context) = {
c.universe.reify { c.literal(c.enclosingPosition.line).splice }
}
def __FILE__Impl(c: Context) = {
c.universe.reify( c.literal(c.enclosingPosition.source.path).splice )
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment