Attempting to write a simple macro in scala-3 that returns the line number at the calling site and am running into some trouble. Most likely something simple I am missing.
Following are my two attempts and the resulting error messages.
class A {
object Source {
// ERROR: malformed macro
// Expected the splice ${...} to contain a single call to a static method.
inline def line = ${ lineImpl() }
def lineImpl()(using scala.quoted.Quotes): scala.quoted.Expr[Int] = {
scala.quoted.Expr(scala.quoted.quotes.reflect.Position.ofMacroExpansion.startLine + 1)
}
}
}
I assumed Source.lineImpl was a static method and that there is only a single call. Maybe this has something to do with the nested object? My second attempt and error message:
object Source {
inline def line = ${ lineImpl() }
def lineImpl()(using scala.quoted.Quotes): scala.quoted.Expr[Int] = {
scala.quoted.Expr(scala.quoted.quotes.reflect.Position.ofMacroExpansion.startLine + 1)
}
}
class B {
def fn(): Unit = {
// ERROR: Cannot call macro method lineImpl defined in the same source file
// This location contains code that was inlined from test.scala:(next line)
val ln = Source.line
}
}
import quoted.*
/** Simple macro, prints out string preceded by source code position. */
inline def deb(str: String): Unit = ${ debImpl('str) }
def debImpl(expr: Expr[String])(using Quotes) = '{ println($posnStrImpl + " " + $expr) }
/** Simplest Macro that shows source code position. Must include parenthesis debb(). Without the parenthesis the macro will not print. */
inline def debb(): Unit = ${ debbImpl }
def debbImpl(using Quotes) = '{ println($posnStrImpl) }
/** An expression debug macro. Prints out source code position followed by expression name, followed by expression value. */
inline def debvar(expr: Any): Unit = ${ debvarImpl('expr) }
def debvarImpl(expr: Expr[Any])(using Quotes) = '{ println($posnStrImpl + " " + ${Expr(expr.show)} + " = " + $expr) }
/** Macro for getting the file name and line number of the source code position. */
inline def posnStr(): String = ${ posnStrImpl }
def posnStrImpl(using Quotes): Expr[String] =
{ val pos = quotes.reflect.Position.ofMacroExpansion
Expr(pos.sourceFile.getJPath.fold("")(_.toString) + ":" + pos.startLine)
}
The slightly more convoluted getJPath.fold("")(_.toString) stops the compiler complaining about the deprecation of jpath.
@tpolecat There doesn’t seem to be a way to get the editor to recognise the column of the source. Maybe its not particularly useful, but I would like to have included it for completeness if the editor didn’t ignore it.