Skip to content

Instantly share code, notes, and snippets.

@travisbrown
Created March 11, 2013 19:13
Show Gist options
  • Save travisbrown/5136824 to your computer and use it in GitHub Desktop.
Save travisbrown/5136824 to your computer and use it in GitHub Desktop.
String interpolation with macro-supported access to positions.
sealed trait Piece
case class Place(p: String) extends Piece
case class Name(n: String) extends Piece
case class LocatedPieces(located: Seq[(String, Piece, (Int, Int))])
object S2 extends ReflectionUtils {
import scala.language.experimental.macros
import scala.language.reflectiveCalls
import scala.reflect.macros.Context
implicit class s2pieces(sc: StringContext) {
def s2(pieces: Piece*) = macro s2Impl
}
def s2Impl(c: Context)(pieces: c.Expr[Piece]*): c.Expr[LocatedPieces] = {
import c.universe._
val ac = companionApplier(c.universe)
val parts = c.prefix.tree match {
case Apply(_, List(Apply(_, parts))) => parts zip pieces map {
case (part, piece) =>
val line = c.literal(piece.tree.pos.line).tree
val column = c.literal(piece.tree.pos.column).tree
ac[(_, _, _)](part, piece.tree, ac[(_, _)](line, column))
}
}
c.Expr(ac[LocatedPieces](ac[Seq[_]](parts: _*)))
}
}
trait ReflectionUtils {
import scala.reflect.api.Universe
def companionApplier(u: Universe) = new {
def apply[A: u.TypeTag](xs: u.Tree*): u.Tree = u.Apply(
u.Select(u.Ident(u.typeOf[A].typeSymbol.companionSymbol), "apply"),
xs.toList
)
}
}
@travisbrown
Copy link
Author

Actually good point—I'm looking back at it and I don't know why it doesn't work.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment