Last active
December 22, 2015 20:39
-
-
Save dcsobral/6527747 to your computer and use it in GitHub Desktop.
Macro that replaces an expression with a REPL-like (minus REPL's "toString") evaluation of the expression.
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
/** | |
* Replaces an expression with a REPL-like evaluation of it. For example, | |
* the expression `2 + 2` would be replaced with this: | |
* | |
* {{{ | |
* scala> 2 + 2 | |
* Int: 4 | |
* }}} | |
* | |
* Clients of REPLinator *must* be compiled with -Yrangepos, until and unless | |
* that becomes default. | |
*/ | |
object REPLinator { | |
import scala.reflect.macros.Context | |
import language.experimental.macros | |
def print[T](v: => T) = macro printImpl[T] | |
def printImpl[T : c.WeakTypeTag](c: Context)(v: c.Expr[T]): c.Expr[String] = { | |
import c.universe._ | |
// This is the thing that requires -Yrangepos | |
def getSource(t: Tree): String = { | |
val pos = t.pos | |
val point = pos.point | |
val startOffset = pos.startOrPoint - point | |
val endOffset = pos.endOrPoint - point | |
val start = pos.column + startOffset - 1 | |
val end = pos.column + endOffset - 1 | |
pos.lineContent.substring(start, end) | |
} | |
def interpolate(params: String*)(trees: Tree*): Tree = | |
Apply( | |
Select( | |
Apply(Ident(newTermName("StringContext")), | |
List(params.map(s => Literal(Constant(s))): _*)), | |
newTermName("s")), | |
List(trees: _*)) | |
val tree = v.tree | |
val parameter = getSource(tree) | |
val tpe = tree.tpe.widen.toString | |
val trees = List(c.literal(parameter).tree, c.literal(tpe).tree, c.resetLocalAttrs(tree)) | |
val prompts = List("scala> ", "\n", ": ", "") | |
c.Expr[String](interpolate(prompts: _*)(trees: _*)) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment