use*_*007 5 scala abstract-syntax-tree
我正在使用一个scala编译器插件,该插件f(x)用块替换函数调用
{
val newvalue = f(x)
newvalue
}
Run Code Online (Sandbox Code Playgroud)
此块的值与相同f(x)。
编译器插件在编译器阶段“ typer”之后立即工作,并通过用块的AST替换f(x)的AST进行上述转换。
在编译器阶段“ typer”之后执行此操作,新创建的块是未包含符号和类型的原始AST及其子AST。我需要调用localTyper来提供原始ASTs符号和类型。
val newVal = (ValDef(Modifiers(0), newTermName("newvalue"), TypeTree(a.tpe), a))
val newIdent = (Ident(newTermName("newvalue")))
localTyper.atOwner(parSymbol).typed(Block(List(newVal), newIdent))
Run Code Online (Sandbox Code Playgroud)
注意:a是函数调用“ f(x)” newVal的AST ,是“ ” 的AST val newvalue = f(x)。并且newIdent是newvalue该块中对“ ” 的引用。parSymbol是旧版AST的所有者的符号“ f(x)”,或a。
上面的代码在大多数情况下都能正常工作。但是,当在应用于函数“ f”的参数中有一些值的定义(无论是显式的还是隐式的)时,编译器都会发出错误。例如,我要转换:
object hello {
def f(x : Unit) = {}
def g = f {
try {
}
catch {
case t : InterruptedException => t
}
}
}
Run Code Online (Sandbox Code Playgroud)
请注意,在函数g的定义中,f占用了一个块
{
try {
}
catch {
case t : InterruptedException => t
}
}
Run Code Online (Sandbox Code Playgroud)
作为其参数,并且t是此参数中新定义的值(隐式)。在这种情况下,在编译器阶段“ icode”中出现错误:
error: scala.reflect.internal.FatalError:
symbol value t#16922 does not exist in hello.g, which contains locals value newvalue#16940.
Method code: def g(): scala.Unit = {
val newvalue: scala#27.runtime#2827.BoxedUnit#4159 = {
hello.this.f({
{
hello.this.liftedTree1$1(t);
scala.runtime.BoxedUnit.UNIT
}
});
scala.runtime.BoxedUnit.UNIT
};
()
}
while compiling: testSynthetic.scala
during phase: icode
library version: version 2.11.7
compiler version: version 2.11.7
reconstructed args: -Xplugin:output.jar -uniqid
last tree to typer: Ident(liftedTree1)
tree position: line 6 of testSynthetic.scala
tree tpe: ()Unit#2648
symbol: (final private[this]) method liftedTree1$1#16976 in object hello#8325
symbol definition: final private[this] def liftedTree1$1#16976(t$1#27328: InterruptedException#151): Unit#2648 (a MethodSymbol)
symbol package: <empty>
symbol owners: method liftedTree1$1#16976 -> object hello#8325
call site: object hello#8325 in package <empty>#4
Run Code Online (Sandbox Code Playgroud)
在“ icode”阶段,理想的转换结果应如下所示:
def g(): Unit = {
val newvalue: Unit = hello.this.f({
{
hello.this.liftedTree1$1();
scala.runtime.BoxedUnit.UNIT
}
});
newvalue
};
Run Code Online (Sandbox Code Playgroud)
但是,在错误消息中:
def g(): scala.Unit = {
val newvalue: scala#27.runtime#2827.BoxedUnit#4159 = {
hello.this.f({
{
hello.this.liftedTree1$1(t);
scala.runtime.BoxedUnit.UNIT
}
});
scala.runtime.BoxedUnit.UNIT
};
()
}
Run Code Online (Sandbox Code Playgroud)
似乎t应该在“ icode”阶段消失,但是由于进行了转换,因此以某种方式保留了该代码,但是t不再提供的定义。我猜想如何为原始AST设置符号是关键。
| 归档时间: |
|
| 查看次数: |
304 次 |
| 最近记录: |