Scala宏的位置如何? [英] What's up with position on Scala macros?

查看:53
本文介绍了Scala宏的位置如何?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试将参数的原始输入字符串获取到宏,但是返回的位置似乎有些偏离.考虑以下宏,例如:

I'm trying to get the original input string of a parameter to a macro, but the returned position seems a bit off. Consider this macro, for example:

object M {
  import scala.reflect.macros.Context
  import language.experimental.macros
  def f[T](v: => T) = macro fImpl[T]
  def fImpl[T : c.WeakTypeTag](c: Context)(v: c.Expr[T]): c.Expr[Unit] = {
    import c.universe._
    val pos = v.tree.pos
    println(pos.lineContent)
    println(" " * pos.column + "^")
    println(" " * pos.point + "^")
    c.literalUnit 
  }
}

当我尝试使用此文件时:

When I try it with this file:

object N extends App {
  val x = 1
  val y = 2
  println(M.f(x + y))
}

我得到以下输出:

  println(M.f(x + y))
                 ^
                                                                  ^

这对我来说没有意义.我希望它指向x,或者相距1.这是怎么回事?

which doesn't make sense to me. I'd expect it to point to x, or be off by one. What's up with that?

推荐答案

Position.columnPosition.line基于1的意义上,这是一个不合一的错误.

It's an off-by-one bug in the sense that Position.column and Position.line are 1-based.

从某种意义上说,这是一个文档错误,因为他们不愿为API写文档,却不愿提及.

It's a documentation bug in the sense that they bothered to document the API but didn't bother to mention that.

您可以使用-Yrangepos和:

val n = pos.column - (pos.point - pos.startOrPoint) - 1
println(" " * n + "^")

或类似的指示树中最早的位置.

or similar to indicate the earliest position in the tree.

println(M.f(x + y))
            ^

更新:

让宏返回给定的表达式,然后使用-Xprint:typer -Yshow-trees进行编译,树是内部Apply节点,位于+:

Letting the macro return the expression it's given, and compiling with -Xprint:typer -Yshow-trees, the tree is the inner Apply node, which is positioned at the +:

      Apply( // def println(x: Any): Unit in object Predef, tree.tpe=Unit
        scala.this."Predef"."println" // def println(x: Any): Unit in object Predef, tree.tpe=(x: Any)Unit
        Apply( // def +(x: Int): Int in class Int, tree.tpe=Int
          "x"."$plus" // def +(x: Int): Int in class Int, tree.tpe=(x: Int)Int
          "y" // val y: Int, tree.tpe=Int
        )
      )

在范围"位置,树的顶部位置包括其下方的所有内容.因此,当point+所在的位置时,范围位置的start是该范围位置所包围的所有内容的最早位置,即树中所有较低的位置.在这种情况下,左边的叶子是x.

With a "range" position, the position of the top of the tree includes everything beneath it. So while point is where the + is, the start of a range position is the earliest position of everything enclosed by the range position, i.e., everything lower in the tree. In this case, the left leaf is the x.

所以差异point - start告诉您备份的距离.

So the difference point - start tells you how far to back up.

(我没有考虑过由于字符编码的不同而导致源文件中的偏移量与列偏移量不同的情况.)

(I haven't considered what if the offsets into the source file are different from column offsets because of differences in character encoding.)

这篇关于Scala宏的位置如何?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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