Groovy ASTTransformation-在闭包内部执行循环的collectionExpression
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Groovy ASTTransformation-在闭包内部执行循环的collectionExpression相关的知识,希望对你有一定的参考价值。
我正在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)
as
for (int j in -> 1..times) // collection expression wrapped in no-arg closure
result += square(i)
正确吗?我认为您缺少一种方法调用表达式,其中闭包是对象表达式,而方法名称是“ call”。
我不确定我为什么要执行此转换,但是我认为在指令选择阶段这样做很晚,并且会导致您错过许多可解析类型/变量并验证类/的编译器步骤。脚本。
以上是关于Groovy ASTTransformation-在闭包内部执行循环的collectionExpression的主要内容,如果未能解决你的问题,请参考以下文章
Groovy编译时元编程 ( ASTTransformation#visit 方法简介 | org.codehaus.groovy.ast.ModuleNode 脚本节点 )
Groovy ASTTransformation-在闭包内部执行循环的collectionExpression
Groovy编译时元编程 ( 编译时方法拦截 | 在 MyASTTransformation#visit 方法中进行方法拦截 )
Groovy编译时元编程 ( 编译时方法拦截 | 在 MyASTTransformation#visit 方法中找到要拦截的方法 )