gpt4 book ai didi

scala - 在 Scala 宏中使用 LabelDef (2.10)

转载 作者:行者123 更新时间:2023-12-04 21:47:42 27 4
gpt4 key购买 nike

我正在试验 scala 2.10 宏功能。我在使用 时遇到问题标签定义 但在某些情况下。在某种程度上,我偷看了编译器的代码,阅读 Miguel Garcia's papers 的摘录但我仍然被困住了。

如果我的理解是正确的,伪定义将是:
LabelDef(labelName, listOfParameters, stmsAndApply)其中 3 个参数是 Trees 和:
- labelName是正在定义的标签 $L 的标识符
- listOfParameters对应于 label-apply 发生时传递的参数,如 $L(a1,...,an) 中,并且可以为空
- stmsAndApply对应于语句块(可能没有)和最终的应用表达式
label-apply 或多或少意味着标签的 GOTO

例如,在一个简单循环的情况下,一个 LabelDef 最终可以应用自己:LabelDef($L, (), {...; $L()})
现在,如果我想定义 2 个相互跳转的 LabelDef:

...
LabelDef($L1, (), $L2())
...
LabelDef($L2, (), $L1())
...

第二个 LabelDef 很好,但编译器在第一个输出错误,“未找到:值 $L2”。我想这是因为 $L2 在尝试应用时尚未定义。这是一棵正在 build 的树,所以这对我来说很有意义。到目前为止我的理解是否正确?因为如果没有预期错误,那意味着我的宏实现可能有问题。

无论如何,我相信一定有办法从 $L1 应用 $L2(即跳转到 $L2),不知何故,但我只是不知道如何去做。有人有这样做的例子,或任何指针?

关于在宏中使用 LabelDef 的其他不清楚点(但现在不太关心)是:
- 第二个参数是什么,具体来说,它在非空时如何使用?换句话说,带参数的标签应用的机制是什么?
- 除了标签应用之外,将第三个参数的最终表达式放入其他任何内容是否有效? (不是我不能尝试,但宏仍然是实验性的)
- 是否可以在 LabelDef 之外执行转发标签应用? (也许这是一个多余的问题)

答案中的任何宏实现示例当然非常欢迎!
干杯,

最佳答案

因为如果没有预期错误,那意味着我的宏实现可能有问题。
是的,这似乎是一个错误 (^^; 虽然我不确定 Block/LabelDef 组合的限制是否故意存在。

def EVIL_LABELS_MACRO = macro EVIL_LABELS_MACRO_impl
def EVIL_LABELS_MACRO_impl(c:Context):c.Expr[Unit] = { // fails to expand
import c.universe._
val lt1 = newTermName("$L1"); val lt2 = newTermName("$L2")
val ld1 = LabelDef(lt1, Nil, Block(c.reify{println("$L1")}.tree, Apply(Ident(lt2), Nil)))
val ld2 = LabelDef(lt2, Nil, Block(c.reify{println("$L2")}.tree, Apply(Ident(lt1), Nil)))
c.Expr( Block(ld1, c.reify{println("ignored")}.tree, ld2) )
}

def FINE_LABELS_MACRO = macro FINE_LABELS_MACRO_impl
def FINE_LABELS_MACRO_impl(c:Context):c.Expr[Unit] = { // The End isn't near
import c.universe._
val lt1 = newTermName("$L1"); val lt2 = newTermName("$L2")
val ld1 = LabelDef(lt1, Nil, Block(c.reify{println("$L1")}.tree, Apply(Ident(lt2), Nil)))
val ld2 = LabelDef(lt2, Nil, Block(c.reify{println("$L2")}.tree, Apply(Ident(lt1), Nil)))
c.Expr( Block(ld1, c.reify{println("ignored")}.tree, ld2, c.reify{println("The End")}.tree) )
}

我认为一个 Block 被解析为 { 语句;表达式 } 因此最后一个参数是表达式。如果 LabelDef “落入”表达式,例如EVIL_LABELS_MACRO 模式,它的扩展在语句中不可见;因此错误“未找到:值 $L2”。

所以最好确保所有 LabelDef 都“落入”语句。 FINE_LABELS_MACRO 这样做并扩展为:
{
$L1(){
scala.this.Predef.println("$L1");
$L2()
};
scala.this.Predef.println("ignored");
$L2(){
scala.this.Predef.println("$L2");
$L1()
};
scala.this.Predef.println("The End")
}

关于scala - 在 Scala 宏中使用 LabelDef (2.10),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11677750/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com