【问题标题】:Scala macro expansion of class with companion: type not found带有伴侣的类的Scala宏扩展:找不到类型
【发布时间】:2014-05-13 21:07:03
【问题描述】:

我正在尝试在扩展为带有伴随对象的类的案例类上定义宏注释,但我遇到了一些问题。

我可以创建一个与类同名的对象,并在其上定义方法。 但是当我尝试使用类的类型名作为方法的返回或参数类型时,我得到一个“未找到:类型”

class term extends StaticAnnotation {
def macroTransform(annottees: Any*) = macro termMacro.impl
}

object termMacro {

def impl(c: Context)(annottees: c.Expr[Any]*): c.Expr[Any] = {
    import c.universe._
    val inputs = annottees.map(_.tree).toList

    val (cls, comp) = annottees.map(_.tree) match {

        case cd@q"$mods class $tpname[..$tparams] $ctorMods(...$paramss) extends { ..$_ } with ..$_ { $self => ..$stats }" :: tail =>

            val paramnames = paramss.head.map {
                case q"$mods val $name: $tpt = $default" => name
            }

            val ctorparams = List(paramss.head ++ Seq(
                q"val position: SourcePosition = (0,0)"
            ))

            val ctorname = TermName(tpname.decodedName.toString)
            //val clstype  =
            (
                q"""
                        import ast.Term
                        case class $tpname(...$ctorparams) extends Term { $self =>
                            def children() = {
                                List(..$paramnames)
                            }

                            ..$stats
                        }
                 """,
                q"""
                        object $ctorname {
                            def unapply(t: $tpname): Option[(Int, Int)] = {
                                Some(Tuple2(3, 4))
                            }
                    }
                """
            )

        case head :: tail =>
            c.abort(c.enclosingPosition, s"The @Term annotation is for case classes, found $head")
    }

    c.error(c.enclosingPosition, showRaw(cls) + "\n" + showRaw(comp))
    c.Expr[Any](Block(List(cls, comp), Literal(Constant(()))))
}
}

例如用法是:@term case class A(x: Term) extends Term,并且会给我编译器错误“未找到:在该定义中的位置 @term 处键入 A”。

我已将位置缩小到对象定义中的 unapply 方法。

感谢任何帮助。 我对 scala 宏非常陌生,因此也欢迎任何进一步的建议。

附带问题:关于在 intellij / gradle 项目中调试宏有什么建议吗?

【问题讨论】:

  • 对我来说它说“方法 unapply 被定义了两次”。您能否将整个项目发布在某个地方,例如在 github 上?
  • 感谢您看这个,尤金。如果可能的话,我想暂时将该项目保密,但由于我希望您能提供进一步的帮助,因此我允许您访问 github 上的 repo。分支 term-macro 包含这里看到的宏定义。
  • 顺便说一句,我之前也看到过类似的错误。似乎案例类自己的伴随对象仍然由编译器创建。
  • 酷!我会看看。我只是克隆和编译吗?
  • 刚刚运行 ./gradlew 说“构建成功”。

标签: scala macros


【解决方案1】:

q"import foo; class Bar" 创建了一个块,因此宏注解会无意中将class Bar 替换为{ import foo; class Bar },这使得Bar 成为一个本地类,从块外部是不可见的。

【讨论】:

  • (重新)移动导入确实修复了它。感谢您花时间检查项目并帮助我解决这个问题。最亲切。自从我在代尔夫特理工大学(为从事 Spoofax 工作的人)听到你的演讲以来,我一直期待着亲自检查 scala 宏。你所做的工作给我留下了最深刻的印象。令人难以置信的是,看到您的项目产生了多少有趣的后续工作。我将密切关注钯项目。
猜你喜欢
  • 1970-01-01
  • 2015-06-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多