groovy - Groovy ASTTransformation-在闭包内部执行forLoop的collectionExpression

标签 groovy compiler-errors abstract-syntax-tree dsl

我正在Groovy中构建自定义DSL,并且我想在闭包内部执行forLoop的条件表达式。

基本上,我在INSTRUCTION_SELECTION编译阶段像这样修改了forLoop

visitForLoop(forLoop: ForStatement) {
.
.
.
.
forLoop.collectionExpression = ClosureExpression(emptyArray(),
                        GeneralUtils.stmt(forLoop.collectionExpression))
}

这是我的Groovy脚本,
int simpleForLoopTest() {

    int result = 0
    int i = 100, times = 3

    for (int j in 1..times) {
        result += square(i)
    }

    return result
}

生成的类文件
final class _simpleForLoopTest_closure1 extends Closure implements GeneratedClosure {
            public _simpleForLoopTest_closure1(Object _outerInstance, Object _thisObject) {
                super(_outerInstance, _thisObject);
            }

            public Object doCall(Object it) {
                return new IntRange(true, 1, DefaultTypeTransformation.intUnbox(times.get()));
            }

            public Integer getTimes() {
                return (Integer)ScriptBytecodeAdapter.castToType(times.get(), Integer.class);
            }

            public Object call(Object args) {
                return this.doCall(args);
            }

            public Object call() {
                return this.doCall((Object)null);
            }

            @Generated
            public Object doCall() {
                return this.doCall((Object)null);
            }
        }

这就是在脚本的类文件中引用闭包的方式
for(Iterator var8 = DefaultGroovyMethods.iterator(new _simpleForLoopTest_closure1(this, this)); var8.hasNext(); result += this.square((CodeStack)iterationStack_13_5.makeNewCall("square:14:19"), i)) 

编译时出现以下错误,
java.lang.VerifyError: Bad local variable type
Exception Details:
  Location:
    TestEventing/ForLoopTest.simpleForLoopTest()I @62: iload
  Reason:
    Type 'groovy/lang/Reference' (current frame, locals[5]) is not assignable to integer
  Current Frame:
    bci: @62
    flags: { }
    locals: { 'TestEventing/ForLoopTest', 'com/testing/flows/episodes/CodeStack', 'java/lang/String', integer, integer, 'groovy/lang/Reference' }
    stack: { }
  Bytecode:
    0x0000000: 2ab4 0020 1239 b600 3d4c 2b57 2ab4 0020
    0x0000010: b600 414d 2c57 2ab4 0020 b600 4401 5703
    0x0000020: 3e1d 5710 6436 0415 0457 06b8 004a b600
    0x0000030: 4db8 004a bb00 4f5a 5fb7 0052 3a05 1505
    0x0000040: 57bb 0054 5912 562b b700 593a 0619 0657
    0x0000050: 013a 07bb 005b 592a 2a19 05b7 005e b800
    0x0000060: 643a 0819 08b9 006a 0100 9900 4619 08b9
    0x0000070: 006d 0100 1246 b800 1ec0 0046 3a07 1906
    0x0000080: b600 7057 1906 b600 743a 0919 0957 2ab4
    0x0000090: 0020 b600 4401 571d 1900 1909 1276 b600
    0x00000a0: 7bc0 0078 1504 b600 7f60 593e 57a7 ffb6
    0x00000b0: 2ab4 0020 1256 2b2c b600 8301 571d ac00
    0x00000c0: 00bf                                   
  Stackmap Table:
    full_frame(@99,{Object[#2],Object[#120],Object[#148],Integer,Integer,Object[#79],Object[#84],Object[#70],Object[#102]},{})
    same_frame_extended(@176)
    full_frame(@191,{},{Object[#53]})


    at java.lang.Class.getDeclaredMethods0(Native Method)
    at java.lang.Class.privateGetDeclaredMethods(Class.java:2701)

注意:完成上述转换后,我还将调用VariableScopeVisitor(source, true).visitClass(node)

有人可以阐明出什么问题吗?

提前致谢。

最佳答案

听起来您正在尝试重写

for (int j in 1..times) {
    result += square(i)
}


for (int j in { -> 1..times}) { // collection expression wrapped in no-arg closure
    result += square(i)
}

那是对的吗?我认为您缺少方法调用表达式,其中闭包是对象表达式,而方法名称是“call”。

我不确定我为什么要进行此转换,但是我认为在指令选择阶段这样做很晚,并且会导致您错过许多解析类型/变量并验证类/脚本的编译器步骤。

关于groovy - Groovy ASTTransformation-在闭包内部执行forLoop的collectionExpression,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59629505/

相关文章:

jenkins - 在 jenkins 管道脚本中获取 gradle 变量

Groovy , -> 是什么意思

r - 在ubuntu上编译R包,ELF头无效

c++ - C++中 "Expected a statement"是什么意思

JavaParser 不更新源文件

java - Groovy:DateUtil.format "yyyy-MM-dd"在格式化时递增一个月

groovy - Jmeter中JedisPool的使用方法

c# - 将连接字符串添加到代码后,为什么会出现错误?

java - 从 Java 源代码生成 AST 报告而不实际运行它

java - ANTLR4 AST 创建 - 如何创建 AstVistor