什么';Scala宏的位置如何?
我试图将参数的原始输入字符串获取到宏中,但返回的位置似乎有点不正确。考虑这个宏,例如:什么';Scala宏的位置如何?,scala,macros,Scala,Macros,我试图将参数的原始输入字符串获取到宏中,但返回的位置似乎有点不正确。考虑这个宏,例如: 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] = {
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
}
}
当我尝试使用此文件时:
object N extends App {
val x = 1
val y = 2
println(M.f(x + y))
}
我得到这个输出:
println(M.f(x + y))
^
^
这对我来说毫无意义。我希望它指向
x
,或者以1为准。这是怎么回事?这是一个一个错误,因为Position.column
和Position.line
是基于1的
从某种意义上说,这是一个文档错误,他们费心去记录API,但却没有提到这一点
您可以使用-Yrangepos
进行编译,并且:
val n = pos.column - (pos.point - pos.startOrPoint) - 1
println(" " * n + "^")
或类似,以指示树中最早的位置
println(M.f(x + y))
^
更新:
让宏返回给定的表达式,并使用-Xprint:typer-Yshow trees
进行编译,树是内部Apply
节点,位于+
:
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
)
)
对于“范围”位置,树顶的位置包括树下的所有内容。因此,虽然点
是+
所在的位置,但范围位置的起点
是范围位置所包含的所有内容的最早位置,即树中较低的所有内容。在这种情况下,左叶是x
因此,不同的point-start
告诉您备份的距离
(我没有考虑到如果源文件中的偏移量由于字符编码的不同而与列偏移量不同会发生什么。)如果您将其更改为
println(M.f(x.+(y))
点移动一到y点,然后使用println(M.f(if(true){x+y}))
它在if中指向f。我怀疑它试图指向树的顶端,调用+或if,尽管它是否应该是另一个问题。也可能存在至少一个一个的错误。这看起来很适合作为一个bug报告给我。如果这个问题是这样的,那会更有趣,你对宏的立场是什么?但是列
指向的是什么?还有,pos.point-pos.startOrPoint
(这两个对我来说都是毫无意义的)的含义是什么?@DanielC.Sobral我只知道足够多的距离位置,以至于引入了一个IDE人员必须修复的bug。至少我也在修复一个bug,所以这是一次清洗。而且,我还以为-Yrangepos会成为默认值?用我有限的知识更新。@DanielC.Sobral在Ah有改进的注释(和代码),我终于意识到,点
,开始
和结束
指向文件中的偏移量,而不是行。@DanielC.Sobral这是一个有用的实现。