【问题标题】:How GOTO statement in Groovy?在 Groovy 中如何 GOTO 语句?
【发布时间】:2011-01-05 10:00:09
【问题描述】:

我看到了这个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;当您在goto 时,执行eval。 DSL 已使用 eval 进行评估。

我不是在寻找“while”循环之类的东西,而是翻译这段代码以便它工作(其他一些语法没问题)

label1: 
a();
b();
goto label1; 

PS: 如果我真的应该使用/想要 GOTO 语句,我不喜欢讨论。 DSL 是一种规范语言,可能无法处理变量、效率等问题。

PS2:可以使用除GOTO之外的其他关键字。

【问题讨论】:

  • 只是一个旁注,标记为 goto 可以比通过延续更容易模拟...
  • @Gabriel:那你能给我胶水吗?
  • 不,我没有胶水:)...我不知道你的 DSL 真的有什么限制,我也不太了解 Groovy,但处理 goto 的一种方法可能是闭包常量的数组/列表/映射和一个执行当前索引/键的方法,可以用 goto 更改。
  • @Gabriel 但为什么贴标签比不贴标签更容易?
  • 这是我写的吗?无标签基本上是每个语句都有一个自动分配的标签,例如电话号码。您可以通过让用户在数组文字中写入来模拟它 - Program[]{statement1, stemaent2,...,stetementN};然后,您可以使用递增索引让 while 循环遍历数组,当您在程序数组中检测到具有有效索引的 goto 时,它可能会发生变化。您可以以相同的方式拥有标签,但您必须添加一个 Map ,当检测到标签语句时,它将为标签分配索引。

标签: groovy dsl transformation goto continuations


【解决方案1】:

您可能想多谈谈您正在尝试构建的语言,也许它很简单,处理转换会过度设计。
使用 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

长话短说,我会说很有可能

【讨论】:

  • 我认为 AST 转换是一个很好的方向。我用关于 DSL 的更多信息更新了起始帖子。
  • @Julian 抱歉,我忘记了这个。我可以给你一个关于 ast 转换的提示,但是现在我重读了你的帖子,我相信你想要构建的语言需要很多思考。基本上,如果你想要一种完全无结构的语言,你需要不止一个技巧来用结构化语言编写它。注入的循环在嵌套方面会受到很大限制,正如有人建议的那样,您可能必须重新设计整个序列。无论如何,如果你想玩ast,这是一个极其简单的例子groovyconsole.appspot.com/script/418002
【解决方案2】:

你不会尝试这个,因为goto 是一个reserved word in Groovy(就像在 Java 中一样),所以在你的 DSL 中使用它会有问题。

这不是reserved word in Scala,所以这不是问题

【讨论】:

  • 那么我们使用关键字gooto?这是关于行为,而不是关于实际的关键字。
【解决方案3】:

您可以使用while 循环模拟ifgoto。它不会很漂亮,它会引入许多不必要的代码块,但它应该适用于任何功能。有一些证据表明,这样重写代码总是可能的,但当然可能并不意味着它很好或容易。

基本上,您将所有局部变量移动到函数的开头并添加一个bool takeJump 局部变量。然后为任何 goto+label 对添加 while(takeJump){+} 对,并将 while 之前和 while 结束之前的标志设置为所需的值。

但老实说,我不推荐这种方法。我宁愿使用一个库,它允许我使用标签和 goto 构建 AST,然后将其直接转换为字节码。

或者使用其他构建在支持goto 的java vm 上的语言。我确定有这样的语言。

【讨论】:

  • 我知道,因此在开始的帖子中我说:“我不是在寻找 'while' 循环之类的东西”;)
  • 使用 if 和 while 会更容易一些,但它并不漂亮,在最坏的情况下可能需要增加 3/2 的代码长度。
【解决方案4】:

把它扔出去,也许你可以有一个作用域开关盒

如果你的 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
}

【讨论】:

    猜你喜欢
    • 2021-02-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-02
    • 1970-01-01
    • 1970-01-01
    • 2014-12-13
    相关资源
    最近更新 更多