2013-09-10 7 views
5

パラメータの元の入力文字列をマクロに取得しようとしていますが、返された位置は少し外れているようです。たとえば、このマクロを考えてみましょう:Scalaマクロの位置付けはどうですか?

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つ離れていてください。どうしたの?

+0

)) 'y 'の点を1点にずらし、' println(Mf(if(true){x + y})) 'でポイントがfの点を指す。私はそれが木の頂点を指し示そうとしていると思われます。+またはifの呼び出しですが、そうするかどうかは別の質問です。少なくとも1つのオフ・バイ・ワン・エラーも存在する可能性があります。これは私にとってバグレポートに適しています。 – wingedsubmariner

+0

質問に「マクロであなたの立場は? –

答えて

3

Position.columnPosition.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 
     ) 
    ) 

と「範囲」の位置では、ツリーの上部の位置にはその下のすべてが含まれます。したがって、point+である間に、範囲位置のstartは、範囲位置によって囲まれたすべてのもののうちの最も早い位置、すなわちツリー内のすべての下位の位置になります。この場合、左の葉はxです。

したがって、差異point - startはバックアップするまでの距離を示します。あなたは `のprintln(MF(X。+(Y)に変更した場合

(私はソースファイルへのオフセットがあるため、文字エンコーディングの違いの列オフセットと異なっている何場合を考慮していなかった。)

+0

しかし、_what_は 'column'を指していますか?そして、 'pos.point - pos.startOrPoint'の意味は何ですか(どちらも私には無意味でした)? –

+0

@ DanielC.Sobral私は、IDEの人が一度修正しなければならなかったバグを導入したばかりの範囲のポジションについて知っています。少なくとも私はバグを修正していたので、それは洗濯物でした。また、私はYrangeposがデフォルトになると思った?私の限られた知識で更新されました。 –

+0

@ DanielC.Sobral https://github.com/scala/scala/pull/2936で改善されたコメント(およびコード)があります。 –