GEP-4
摘要
AstBuilder 在 Groovy 1.7 中引入,用于简化编写 AST 变换的任务。 “fromCode” 方法允许您从代码片段生成 AST。目前,AstBuilder fromCode API 接受一个闭包作为参数,闭包中的代码将转换为 AST。AstBuilder 的一个限制是闭包参数不允许引用周围环境中的变量:无法将参数传递到代码块中。最初讨论过这个问题,但该想法被认为过于复杂,无法融入 1.7 版本。
此 AST 模板功能允许您将参数传递到 AstBuilder 中。与 GString 插值中 $ 的作用类似,需要一种方法将封闭作用域中的变量绑定到 AstBuilder 闭包中。提议的语法是使用牛津括号(见下文)。包含 GEP 4 - AstBuilder AST 模板的 AstBuilder 闭包将绑定括号内的变量。
方法
牛津括号用于将封闭作用域中的变量绑定或准引用到 AstBuilder 参数中。
示例 1:字符串连接
def constant = new ConstantExpression("World")
List<ASTNode> greeting = AstBuilder.buildFromCode { "Hello" + [ | constant | ] }
生成 AST
BlockStatement
-> ExpressionStatement
-> BinaryExpression +
-> ConstantExpresssion - Hello
-> ConstantExpression - World
示例 2:生成 println
new AstBuilder().buildFromCode { println([ | message | ]) }[0]
等效于调用此方法
private Statement createPrintlnAst(String message) {
return new ExpressionStatement(
new MethodCallExpression(
new VariableExpression("this"),
new ConstantExpression("println"),
new ArgumentListExpression(
new ConstantExpression(message)
)
)
)
}
示例 3:方法的记忆化
假设您已将现有的方法 AST 存储在一个名为“methodNode”的变量中
def methodNode = ...
def parameters = methodNode.parameters
def newMethod = new AstBuilder().buildFromCode {
if (cache.contains([ | parameters | ])) {
return cache.get([ | parameters | ])
}
def result = [ | methodNode.code | ]
cache.put([ | parameters | ])
return result
}
methodNode.code = newMethod[0]
备选方案
有很多语法备选方案
-
Lisp 使用 ´ 和 ,
-
Template Haskell 使用类似于牛津括号但语义略有不同的语法
-
Boo 使用 GEP 4 - AstBuilder AST 模板和 $,但语义略有不同
考虑过使用 $,但由于它已经是具有意义的标识符,因此无法使用。Boo 元方法比较 Boo 元方法功能与 Groovy AST 变换功能重叠。Boo 没有提供带有单独定义的 AstTransformation 子类的 @AstTransformation 接口,而是提供元方法,在编译时调用并生成 AST 变换。
Groovy 提供 AstBuilder 将代码转换为 AST,而 Boo 使用牛津括号。GEP-4 提议使用牛津括号来表示 AST 变量模板,而 Boo 使用 $。考虑 Groovy 中简单的 println AST
new AstBuilder().buildFromCode {
println([ | message | ])
}[0]
与 Boo 中类似的结构相比
[Meta]
static def methodname(expr as Expression):
[| println($expr) |]
GEP-4 提议的语法与 Boo 相反:使用牛津括号表示 AST 模板,而不是 $。$ 已经是 Java 中的字符,可以作为变量名称的一部分。
使用相反的语法没有真正的问题。从 Boo AST 变换编写者迁移到 Groovy 的人数很可能非常少。
参考资料和有用链接
邮件列表讨论
-
groovy-dev: Groovy AstBuilder AST 模板
更新历史
- 1 (2010-02-16)
-
从 Codehaus wiki 中提取的版本
- 2 (2018-10-14)
-
大量细微调整