标签: scala-macros

检索将分配Scala宏调用的值的名称

我正在尝试编写一个宏,它将包装一个函数并从其调用将赋值的值中扣除一个参数.

object TestMacros {
  def foo(name: String): String = name.toUpper
  def bar = macro barImpl
  def barImpl(c: Context): c.Expr[String] = {
    import c.universe._
    //TODO extract value name (should be baz)
    c.Expr[String](Apply(
      Select(newTermName("TestMacros"), newTermName("foo")), // Probably wrong, just typed it quickly for demonstration purposes
      List(Literal(Constant("test"))))) // Should replace test by value name
  }
}

object TestUsage {
  val baz = bar // should be BAZ
}
Run Code Online (Sandbox Code Playgroud)

我不知道这是否足够清楚.我已经调查了c.prefix和c.macroApplication而没有成功.我在没有宏天堂编译器插件的情况下使用Scala 2.10.2.

macros scala scala-2.10 scala-macros

2
推荐指数
1
解决办法
880
查看次数

Scala 宏:如何获取泛型列表的类型对象

我正在研究一个 Scala 宏,我想将 a 的类型与 aSymbol相匹配List[T],其中 theT是给定的Type。我已经有了类型参数的Type对象T

很容易得到 的 Type 对象List[_]

  val listType = c.weakTypeOf[List[_]]
Run Code Online (Sandbox Code Playgroud)

有了这个,我已经可以检查 typeSignature

  sourceParam.typeSignature match {
    case paramType if paramType <:< listType =>
      ....
  }
Run Code Online (Sandbox Code Playgroud)

但是我想用 来检查 paramType List[T],那么我如何制作一个类型,我可以在其中获取List[_]和某个Type对象并使其成为新类型?

scala type-parameter scala-macros

2
推荐指数
1
解决办法
377
查看次数

如何将参数传递给Scala宏注释impl?

当注释的参数是常量时,我​​获得了成功,例如:

@Annotation(2)
class AnnotatedClass
Run Code Online (Sandbox Code Playgroud)

因为我可以通过以下方式获取宏中的值impl:

c.prefix.tree match {
  case Apply(_, List(Literal(Constant(x)))) => x.toInt
}
Run Code Online (Sandbox Code Playgroud)

但是当注释的参数不是常数时,我很难过,比如:

object Obj {val n = 2}

@Annotation(Obj.n)
class AnnotatedClass
Run Code Online (Sandbox Code Playgroud)

在假开始类似这样的问题,我可以匹配c.prefix.tree一次拉出名称Objn,但我如何获得的价值Obj.n

annotations scala scala-macros

2
推荐指数
1
解决办法
289
查看次数

Scala 3:内联与引用(宏)

最近我有一个在Scala 3中编写宏的经验。我用于inline简单的函数和引用代码,scala.quoted用于更复杂的操作。

似乎这两个功能都用编译时生成的代码替换了一些运行时代码,但inline有一些限制。

它们之间有什么区别,为什么inline不能到处使用引用代码代替?

scala metaprogramming scala-macros

2
推荐指数
1
解决办法
126
查看次数

Scala 3 宏特征参数

这是基本设置:

trait MyProduct[A, B](a: A, b:  B)
class X
class Y

class XxY(x: X, y: Y) extends MyProduct(x,y)
Run Code Online (Sandbox Code Playgroud)

我正在尝试检查该MyProduct特征的论据。更具体地说,我想提取一些信息,例如字符串“x”和“y”,它们指示 的哪些字段XxY传递给MyProduct.

重要的是,我需要满足具有相同类型的多个字段的情况,例如class XxYxY(x: X, y1: Y, y2: Y) extends MyProduct3(x, y1, y2),因此从类型参数进行推理是不够的。

我想也许问题是我还没有找到一种方法来为条款extends本身添加符号。我可以找到ClassDeffor XxY,从中我可以提取parents并获取已经构造的类型MyProduct[X,Y]。我还查看了symbol.declarations封闭模块和XxY.<init>函数的 ,以查看是否有可用于查找参数的数据,但这些似乎都没有我正在寻找的信息。

查看封闭模块的树让我认为这些信息可能被删除,而是需要从源代码解析为文本,但我希望有人有更好的解决方案。

从评论中编辑:

作为输入,我有一个Type封闭对象/模块的实例。例如:

trait MyProduct[A, B](a: A, b:  B)
class X
class Y

class XxY(x: X, y: Y) extends MyProduct(x,y)
Run Code Online (Sandbox Code Playgroud)

作为输出,我想要一些允许我检查 extends 子句中使用的特征的参数的东西。

scala scala-macros scala-3

2
推荐指数
1
解决办法
346
查看次数

在宏中查找方法参数的实际类型

假设我有一个宏实现

def testImpl[T](c:Context)(implicit wtt:c.WeakTypeTag[T]):c.Tree = {
    import c.universe._

    def info(msg: Any) = c.info(c.enclosingPosition, msg.toString, true)

    val parameter = wtt.tpe.member(TermName("f")).paramLists(0)(0)

    info(parameter.typeSignature)

    q"{}"
}
Run Code Online (Sandbox Code Playgroud)

和宏定义

def test[T]:Unit = macro DerivingImpl.testImpl[T]
Run Code Online (Sandbox Code Playgroud)

此宏f在其类型参数中查找函数,并打印有关其第一个参数类型的信息.

现在如果我像这样使用这个宏

trait Trait[A] {
    def f(x:A): Int
}

test[Trait[Int]]
Run Code Online (Sandbox Code Playgroud)

我被A打印了.我想得到Int.我理解调用member返回的方法符号没有关于具体应用类型的信息.那么,找到参数的实际类型的正确方法是什么?

谢谢.

scala scala-macros

1
推荐指数
1
解决办法
303
查看次数

使用java中的scala宏

目前我正在编写一个scala宏库,我想也可以从java中使用它.

但我想不出一种方法来访问scala宏方法形式的java源代码.我们有什么方法可以使用java中的scala宏方法.

scala scala-java-interop scala-macros

1
推荐指数
1
解决办法
274
查看次数

如何使用ansi代码为scala中的标准输出着色

是否有一个 Scala 库可以帮助对写入标准输出的文本进行着色?

这个库应该利用 scala 字符串插值机制。

scala scala-macros

1
推荐指数
1
解决办法
477
查看次数

Scala宏自动生成流畅的构建器

我正在与外部Java API交互,如下所示:

val obj: SomeBigJavaObj = {
  val _obj = new SomeBigJavaObj(p1, p2)
  _obj.setFoo(p3)
  _obj.setBar(p4)
  val somethingElse = {
    val _obj2 = new SomethingElse(p5)
    _obj2.setBar(p6)
    _obj2
   }
  _obj.setSomethingElse(somethingElse)
  _obj
}
Run Code Online (Sandbox Code Playgroud)

基本上,Java API公开了.setXXXX许多返回void和设置内容的方法.我无法控制这些外部POJO.

因此,我想编写一个流畅的buildScala宏来检查对象,并.withXXXX()为每个void setXXXX()返回的方法创建一个builder-pattern类型方法 this:

val obj: SomeBigJavaObj =
  build(new SomeBigJavaObj(p1, p2))
    .withFoo(p3)
    .withBar(p4)
    .withSomethingElse(
       build(new SomethingElse(p5))
         .withBar(p6)
         .result()
    )
    .result()
Run Code Online (Sandbox Code Playgroud)

这可能吗?我知道我无法使用def宏生成新的顶级对象,所以我可以使用类似的人体工程学设置.

scala builder scala-macros scala-macro-paradise scalameta

1
推荐指数
1
解决办法
425
查看次数

是否可以将抽象类或特征上的宏应用于所有子类?

假设我Foo在某个库中具有某些特征(或抽象类),该特征通常由用户代码扩展并且需要某些方法numArgs

trait Foo {
  // Number of arguments to the default constructor
  def numArgs: Int
}
Run Code Online (Sandbox Code Playgroud)

现在numArgs写起来很简单,但是我想生成的是令人讨厌的样板。我可以通过反射来做到这一点,但是它很丑陋,并且无法移植到其他后端,例如ScalaJS,ScalaNative或GraalVM。

是否可以编写只能应用于Foo而不是在的每个子类上都需要)我可以应用的宏注释,Foo以便生成该方法?

scala scala-macros

1
推荐指数
1
解决办法
73
查看次数