最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

Passing string as the parameter to ValDef left-hand-side's method invoke inside quote block in Scala 3 macro annotation

programmeradmin4浏览0评论

I am trying implementing a macro annotation with such effect:

@MarkNode
val dataAbc = new Data()

which generates

val dataAbc = new Data()
dataAbc.setCodegenSuffix("dataAbc")

And, some of examples used the form like below

@experimental
class MarkNode extends MacroAnnotation:
  override def transform(using quotes: Quotes)(tree: quotes.reflect.Definition): List[quotes.reflect.Definition] =
    import quotes.reflect.*

What should the type be when I want the macro generates Expr[Something] instead of Definitions? With Scala version 3.3.4 So that package in use is .scala-lang.scala3-compiler-3.3.4-provided

tree match {
  case ValDef(lhs, tpt, rhs) =>
    val term = Ident.copy(tree)(lhs).asExprOf[Data]
    val invoke = '{ $term.setCodegenSuffix('lhs) }
symbol literal 'lhs is no longer supported,
use a string literal "lhs" or an application Symbol("lhs") instead,
or enclose in braces '{lhs} if you want a quoted expression.
For now, you can also `import language. deprecated.
symbolLiterals` to accept the idiom,
but this possibility might no longer be available in the future.

But Symbol did not have an apply function.

And the LSP reported error that the usage of 'lhs is no longer supported. I don't want deprecated features. So what should I do to pass the lhs which is typed in String to the method call in quoted block?

Full snippet:

import scala.annotation.{MacroAnnotation, experimental}
import scala.collection.mutable.ListBuffer
import scala.quoted.*

@experimental
class MarkNode extends MacroAnnotation:
  override def transform(using quotes: Quotes)(tree: quotes.reflect.Definition): List[quotes.reflect.Definition] =
    import quotes.reflect.*

    val buffer = new ListBuffer[Definition]()

    tree match {
      case ValDef(lhs, tpt, rhs) =>
        val data = Ident.copy(tree)(lhs).asExprOf[Data]
        val invoke = '{ $data.setCodegenSuffix('lhs) }
    }
    
    buffer.result() // Well I think it's wrong. Because `invoke` is obviously an Expr[Unit]

Scala's way of meta programming seems to be more flex, but it's really not friendly to newbies. I've referenced many examples and one of is via asTerm but it seems that Scala 3 versions are varying so that some of the types those examples used cannot be found. And documentation Scala 3 now has seems did not cover such usage. So sad I really have no other way? :(

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论