Created
January 11, 2014 20:38
-
-
Save pedrofurla/8376407 to your computer and use it in GitHub Desktop.
Example of how to get source locations using scala macros
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package slickdemo | |
import scala.reflect.macros.Context | |
import scala.language.experimental.macros | |
object Macros { | |
// scala.reflect.runtime.currentMirror | |
// universe.reify | |
/** Given a Tree, extracts the source code in its range. Assumes -Yrangepos scalac argument. */ | |
def extractRange(t:Context#Tree):Option[String] = { | |
val pos = t.pos | |
val source = pos.source.content | |
if(pos.isRange) Option(new String(source.drop(pos.start).take(pos.end-pos.start))) else None | |
} | |
/** Gives the source code of an expression and the result of the expr in a tuple */ | |
def sourceExpr[A](a: A): (String, A) = macro sourceExprImpl[A] | |
// previously based on log and logImpl | |
// from https://github.com/retronym/macrocosm/blob/master/src/main/scala/com/github/retronym/macrocosm/Macrocosm.scala | |
def sourceExprImpl[A: c.WeakTypeTag](c: Context)(a: c.Expr[A]): c.Expr[(String, A)] = { | |
import c.universe._ | |
val portion = extractRange(a.tree) getOrElse "" | |
val t2 = Select(Select(Ident(newTermName("scala")), newTermName("Tuple2")), newTermName("apply")) | |
// following advice from https://github.com/kevinwright/macroflection/blob/master/kernel/src/main/scala/net/thecoda/macroflection/Validation.scala | |
//clone to avoid "Synthetic tree contains nonsynthetic tree" error under -Yrangepos | |
val adup: Tree = a.tree.duplicate | |
val tree = treeBuild.mkMethodCall(t2, List(Literal(Constant(portion)), adup)) | |
val expr = c.Expr[(String, A)](tree) | |
expr | |
} | |
def debugExpr[A](a: A): A = macro debugExprImpl[A] | |
def debugExprImpl[A: c.WeakTypeTag](c: Context)(a: c.Expr[A]): c.Expr[A] = { | |
import c.universe._ | |
val portion = extractRange(a.tree) getOrElse "" | |
val adup: Tree = a.tree.duplicate | |
val expr = c.Expr[A](adup) | |
/* | |
val t = Block( | |
ValDef(Modifiers(), newTermName("x"), TypeTree(), adup), | |
Apply(Select(Ident(newTermName("scala.Predef")), newTermName("println")), List(Ident(newTermName("x")))), | |
Ident(newTermName("x")))*/ | |
val const=c.Expr[String](Literal(Constant(portion))) | |
reify { | |
println(const.splice) | |
expr.splice | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment