在运行时访问源代码文本的宏 [英] Macro to access source code text at runtime

查看:20
本文介绍了在运行时访问源代码文本的宏的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

是否已经有或者是否有一个 Scala 宏可以让我访问源代码的文本?例如我想写这样的代码:

Is there already or is it possible to have a Scala macro that gives me access to the text of the source? For instance I would like to write code like this:

val list = List(1, 2, 3)
val (text, sum) = (list.sum).withSource{(source, sum) => (source, sum)}
// would return ("list.sum", 6)
(list.sum).withSource{(source, sum) => println(s"$source: $sum"}
// prints list.sum: 6

推荐答案

你真的想要一个源代码还是Tree就够了?

Do you really want a source code or Tree is enough?

对于 Tree,您可以像这样使用 Contextprefix:

For Tree you could use prefix of Context like this:

import scala.language.experimental.macros
import reflect.macros.Context

implicit class WithSourceHelper[T](source: T) {
  def withSource[R](f: (String, T) => R): R = macro withSourceImpl[T, R]
}

def withSourceImpl[T, R](c: Context)(f: c.Expr[(String, T) => R]): c.Expr[R] = {
  import c.universe.{reify, Apply}

  val source = c.prefix.tree match {
    case Apply(_, List(s)) => s
    case _ => c.abort(c.enclosingPosition, "can't find source")
  }

  reify{ f.splice.apply(c.literal(source.toString).splice, c.Expr[T](source).splice) }
}

用法:

scala> val (x, y) = (1, 2)
x: Int = 1
y: Int = 2

scala> {x + y}.withSource{ (s, r) => s"$s = $r" }
res15: String = x.+(y) = 3

scala> val list = List(1, 2, 3)
list: List[Int] = List(1, 2, 3)

scala> val (text, sum) = (list.sum).withSource{(source, sum) => (source, sum)}
text: String = list.sum[Int](math.this.Numeric.IntIsIntegral)
sum: Int = 6

scala> (list.sum).withSource{(source, sum) => println(s"$source: $sum")}
$line38.$read.$iw.$iw.$iw.list.sum[Int](math.this.Numeric.IntIsIntegral): 6

这篇关于在运行时访问源代码文本的宏的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆