【问题标题】:Using def-macros to capture source code [duplicate]使用 def-macros 捕获源代码 [重复]
【发布时间】:2013-05-01 17:19:21
【问题描述】:

(对于 TL;DR,请转到粗体部分)

我有一个带有序列化的干净封闭类型类系统(与 POJO 序列化问题分离)。例如:

trait Expr
case class Const(i: Int) extends Expr
case class BinOp(a: Expr, b: Expr, op: Int) extends Expr

但在某些情况下,我需要捕获一个闭包。例如:

case class Map(a: Expr, fun: Expr => Expr) extends Expr

现在,我已经通过fun 的 POJO 序列化(ObjectOutputStream 等)解决了这个问题。我的脚被严重咬伤,因为我无法在 Scala 2.10 中阅读我在 2.9 中序列化的内容。在这种情况下,我真的需要确保我可以独立于 Scala 版本来取回我的东西。

所以...我一直在想我可以使用宏来“备份”源代码,这样如果 POJO 反序列化失败,我可以从源代码重新生成函数(使用就地编译器/口译员)。

我的想法是

object Map {
  def apply(a: Expr, fun: Expr => Expr): Map = macro applyImpl
  private def applyImpl = ???

  def unapply(m: Map): Option[(Expr, Expr => Expr)] = Some(m.a -> m.fun)
}
trait Map extends Expr {
  def a: Expr
  def fun: Expr => Expr
}

implicit class ExprOps(val ex: Expr) extends AnyVal {
  def map(fun: Expr => Expr) = Map(ex, fun)
}

是否可以轻松捕捉到调用的来源像

//           |------------- source of this -------------|
someExpr.map { case Const(i) => Const(i*i); case x => x }

(我的猜测是def-macro需要已经在ExprOpsmap函数中)。

【问题讨论】:

  • 我不认为你可以得到源码,但你可以得到Tree:def applyImpl(c: Context)(a: c.Expr[Expr], fun:c.Expr[Expr => Expr]): c.Expr[Map] = { val source = c.universe.show(fun.tree); ... }
  • @senia 感谢您的链接和评论。实际上,我不需要原始源代码,因为它不会(可能)向用户显示,我只想要一个可以重新编译到同一棵树的源代码,即使是 Tree 的序列化版本更改(所以我不想直接序列化树)。所以,我看看这个universe.show,可能确实够用了。

标签: scala macros reify


【解决方案1】:

文本替换宏在这种事情上很棒。 Scala 没有附带它们,但考虑编写自己的!转换例如

{# case Const(i) => Const(i*i); case x => x #}

({ case Const(i) => Const(i*i); case x => x }, """case Const(i) => Const(i*i); case x => x""")

应该很容易;那么你只需要在编译之前进行预处理。如果您希望您的 IDE 不会被不同的行长混淆,您可以将字符串存储在单独的对象中,例如

{# _+7 #}/*STORE*/

({_+7}, Store.aW4)

...

object Store {
   val aW4 = """_+7"""
}
//(EOF)

(为了获得最佳效果,base-64 对捕获的文本进行编码。只要您以递归方式工作并且知道可能发生嵌套,嵌套就可以正常工作。)

【讨论】:

  • 我需要能够在运行时使用嵌入式解释器执行此操作。在我的编译项目/IDE中,我已经可以访问源代码:)我当然可以从解释器中捕获文本(我以前做过),但是我需要摆弄寻找源位置(除非当然,我会添加转义字符,就像您对 # 所做的那样。
猜你喜欢
  • 2018-07-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-06-11
  • 2012-07-10
  • 2012-01-23
  • 2012-11-25
  • 2012-01-13
相关资源
最近更新 更多