我看到了这篇关于 Scala 延续的精彩博客文章,它“模拟”了 Scala 语言中的
GOTO
语句。 (阅读更多关于这里继续)
我希望在编程语言 Groovy 中也能拥有同样的功能。我认为在 Groovy 编译器阶段转换 中这是可能的。
我正在研究领域特定语言 (DSL),并且首选嵌入到 Groovy 中。我想要
GOTO
声明,因为 DSL 是一种非结构化语言(并且是从工作流程图生成的)。我需要一个“带标签”的 goto 语句,而不是行号。
DSL 是一种用于工作流定义的语言,并且由于节点之间的箭头没有限制,因此需要
goto
。 (或带有 while
等不可读的代码)
作为 Groovy 和 Scala 的初学者,我不知道是否可以将 Scala 解决方案翻译为 Groovy,但我认为 Groovy 中有延续。
我正在寻找一种算法/代码来模拟 Groovy 中的标记 goto。我想到的一种算法是重复使用
eval
;当您处于 eval
时,执行 goto
。
DSL 已通过 eval
进行评估。
我不是在寻找“while”循环或其他东西,而是翻译这段代码以使其工作(其他一些语法没有问题)
label1:
a();
b();
goto label1;
PS: 我不喜欢讨论我是否应该真正使用/想要 GOTO 语句。 DSL 是一种规范语言,可能无法处理变量、效率等问题。
PS2:可以使用其他关键字
GOTO
。
一种方法是使用 Groovy AST 转换。这是一把大锤子,并且可能对您想要构建的语言进行了过度设计。使用 AST 是 Groovy 人们多年来一直在做的事情,它真的很强大。
Spock 框架人员重写了您创建的测试,用标签注释代码。 https://github.com/spockframework/spock
哈姆雷特·达西曾多次就此事发表过演讲。在他的博客上也可以找到一些帖子。 http://hamletdarcy.blogspot.com/
有用的起点:
长话短说,我想说这很有可能。
您可以使用
if
循环模拟 goto
和 while
。它不会很漂亮,它会引入许多不必要的代码块,但它应该适用于任何函数。有一些证据表明,这样重写代码总是可能的,但当然可能并不意味着它很好或很容易。
基本上,您将所有局部变量移至函数的开头并添加一个
bool takeJump
局部变量。然后为任何 goto+label 对添加一个 while(takeJump){
+}
对,并将 while 之前和 while 结束之前的标志设置为您想要的值。
但说实话我不推荐这种方法。我宁愿使用一个库,它允许我构建带有标签和 goto 的 AST,然后将其直接转换为字节码。
或者使用基于 java vm 构建的支持
goto
的其他语言。我确信有这样一种语言。
只要把这个扔出去,也许你可以有一个作用域开关盒
因此,如果您的 DSL 是这样说的:
def foo() {
def x = x()
def y
def z
label a:
y = y(x)
if(y < someConst) goto a
label b:
z = y(z)
if(z > someConst) goto c
x = y(y(z+x))
z = y(x)
label c:
return z;
}
你的“编译器”可以把它变成这样:
def foo() {
String currentLABEL = "NO_LABEL"
while(SCOPED_INTO_BLOCK_0143) {
def x
def y
def z
def retval
switch(currentLABEL) {
case "NO_LABEL":
x = x()
case "LABEL_A"
y = y(x)
if(y < someConst) {
currentLABEL = "LABEL_A"
break
}
case "LABEL_B"
z = y(z)
if(z > someConst) {
currentLabel = "LABEL_C"
break
}
x = y(y(z+x))
z = y(x)
case "LABEL_C"
SCOPED_INTO_BLOCK_0143 = false
retval = z
}
}
return retval
}