Scala编译器生成抛出代码

时间:2012-12-04 14:13:49

标签: scala compiler-construction scala-compiler

我正在尝试更改其他人编写的编译器插件,该插件直接在typer之后运行,我想生成抛出异常的代码。

Exception类如下所示:

case class MyException(message: String) extends Exception(message)

在实际代码中,这是一个内部类。

我看了他是如何得到一个固定班级的符号并且做得类似,我不知道是否有更好的方法,但这是他如何做到的:

val exceptionClass = MyException.getClass.getName
val exceptionName = if (exceptionClass.last == '$') exceptionClass.dropRight(1) else exceptionClass
val symbol = rootMirror.getModuleByName(newTermName(exceptionName))

要抛出异常,我这样做了:

import CODE._
THROW(symbol, Literal(Constant("My message")))

我认为,以下也是等效的(和产量等效行为)

Throw(symbol.tpe, Literal(Constant("My Message")))
Throw(NEW(symbol, Literal(Constant("My message"))))
Throw(New(symbol.tpe, Literal(Constant("My message"))))

但我有一个例外:

== Enclosing template or block ==

Apply( // val <error>: <error> in class <error>
  new MyException.type."<init>" // val <error>: <error> in class <error>, tree.tpe=<error>
  Nil
)

== Expanded type of tree ==

TypeRef(TypeSymbol(class MyException extends ))

uncaught exception during compilation: scala.reflect.internal.Types$TypeError
error: scala.reflect.internal.Types$TypeError: MyException.type does not have a constructor
...

我想我不得不以不同方式使用“新”,有谁知道这是如何正确完成的?

1 个答案:

答案 0 :(得分:2)

Scala邮件列表的某个人告诉我解决方案:

我应该以不同的方式获得符号,我需要类的符号,而不是模块的符号,如果它是调用方法的对象,则使用后者,但是我们需要这里的类,所以不需要< / p>

val symbol = rootMirror.getModuleByName(newTermName(exceptionName))

我写

val symbol = rootMirror.getClassByName(newTermName(exceptionName))