我看到这个nice blog post about a Scala continuations“模仿”Scala语言中的GOTO
语句。 (阅读更多关于Continuations here)
我想在编程语言Groovy中使用相同的东西。我认为这可能在Groovy compiler phase transformation内。
我正在研究领域特定语言(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
。
答案 0 :(得分:5)
您可能想要更多地了解您正在尝试构建的语言,也许这很简单,处理转换将会过度工程化。
使用AST是人们多年来一直在做的事情,它真的很强大
spock框架人员重写你用标签创建注释代码的测试。 http://code.google.com/p/spock/
哈姆雷特·德·艾西已经就此事发表了几次演讲。他的博客上也可以找到几个帖子。 http://hamletdarcy.blogspot.com/
Cedric Champeau描述了他建立的一个有趣的转变及其演变http://www.jroller.com/melix/
可能会遗漏很多其他人,但我记得那些人
您可能已经知道但可能非常有用的起点。 http://groovy.codehaus.org/Compile-time+Metaprogramming+-+AST+Transformations
http://groovy.codehaus.org/Building+AST+Guide
长话短说,我说它很可能
答案 1 :(得分:1)
由于goto
是reserved word in Groovy(就像在Java中一样),因此您无法在任何地方尝试此操作,因此在DSL中使用它会有问题。
这不是reserved word in Scala,所以这不是问题
答案 2 :(得分:1)
您可以使用if
循环模拟goto
和while
。它不会很漂亮,它会引入许多不必要的代码块,但它应该适用于任何函数。有一些证据表明,总是可以重写这样的代码,但当然可能并不意味着它很好或很容易。
基本上,您将所有局部变量移动到函数的开头并添加bool takeJump
局部变量。然后为任何goto +标签对添加while(takeJump){
+ }
对,并将while之前和之前的标志设置为所需的值。
但说实话,我不推荐这种做法。我宁愿使用一个库,它允许我使用标签和gotos构建一个AST,然后将其直接转换为字节码。
或者使用支持goto
的java vm上构建的其他语言。我确信有这样的语言。
答案 3 :(得分:1)
把它扔到那里,也许你可以有一个范围的开关案例
所以,如果您的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
}