Skip to content

Instantly share code, notes, and snippets.

@dcsobral
Last active December 22, 2015 20:39
Show Gist options
  • Save dcsobral/6527747 to your computer and use it in GitHub Desktop.
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.
/**
* 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