Skip to content
Permalink
Browse files
GROOVY-10579: SC: write array component type for optimized for-each loop
  • Loading branch information
eric-milles committed Apr 13, 2022
1 parent df0a7b8 commit 5da51e1fbe82237361ecf24eb8b085e5c82e2cdd
Showing 4 changed files with 40 additions and 27 deletions.
@@ -107,20 +107,20 @@ protected void writeForInLoop(final ForStatement loop) {
compileStack.pop();
}

private void writeOptimizedForEachLoop(final ForStatement loop, final Parameter loopVariable, final Expression collectionExpression, final ClassNode collectionType) {
private void writeOptimizedForEachLoop(final ForStatement loop, final Parameter loopVariable, final Expression arrayExpression, final ClassNode arrayType) {
CompileStack compileStack = controller.getCompileStack();
OperandStack operandStack = controller.getOperandStack();
MethodVisitor mv = controller.getMethodVisitor();
AsmClassGenerator acg = controller.getAcg();

BytecodeVariable variable = compileStack.defineVariable(loopVariable, false);
BytecodeVariable variable = compileStack.defineVariable(loopVariable, arrayType.getComponentType(), false);
Label continueLabel = compileStack.getContinueLabel();
Label breakLabel = compileStack.getBreakLabel();

// load array on stack
collectionExpression.visit(acg);
arrayExpression.visit(acg);
mv.visitInsn(DUP);
int array = compileStack.defineTemporaryVariable("$arr", collectionType, true);
int array = compileStack.defineTemporaryVariable("$arr", arrayType, true);
mv.visitJumpInsn(IFNULL, breakLabel);

// $len = array.length
@@ -1962,6 +1962,7 @@ public void visitForLoop(final ForStatement forLoop) {
// for (int i=0; i<...; i++) style loop
super.visitForLoop(forLoop);
} else {
visitStatement(forLoop);
collectionExpression.visit(this);
ClassNode collectionType = getType(collectionExpression);
ClassNode forLoopVariableType = forLoop.getVariableType();
@@ -1985,7 +1986,7 @@ public void visitForLoop(final ForStatement forLoop) {
}
typeCheckingContext.controlStructureVariables.put(forLoop.getVariable(), componentType);
try {
super.visitForLoop(forLoop);
forLoop.getLoopBlock().visit(this);
} finally {
typeCheckingContext.controlStructureVariables.remove(forLoop.getVariable());
}
@@ -35,27 +35,6 @@ class LoopsSTCTest extends StaticTypeCheckingTestCase {
}
}

void testForInLoopOnArray() {
assertScript '''
String[] strings = ['a','b','c']
for (string in strings) {
string.toUpperCase()
}
'''
}

// GROOVY-8882
void testForInLoopOnString() {
assertScript '''
for (s in 'abc') assert s instanceof String
for (String s in 'abc') assert s instanceof String
'''
assertScript '''
for (char c in 'abc') assert c instanceof Character
for (Character c in 'abc') assert c instanceof Character
'''
}

void testMethodCallWithEachAndDefAndTwoFooMethods() {
shouldFailWithMessages '''
Date foo(Integer x) { new Date() }
@@ -193,6 +172,39 @@ class LoopsSTCTest extends StaticTypeCheckingTestCase {
'''
}

void testForInLoopOnArray() {
assertScript '''
String[] strings = ['a','b','c']
for (string in strings) {
string.toUpperCase()
}
'''
}

// GROOVY-10579
void testForInLoopOnArray2() {
assertScript '''
int[] numbers = [1,2,3,4,5]
int sum = 0
for (i in numbers) {
sum += i
}
assert sum == 15
'''
}

// GROOVY-8882
void testForInLoopOnString() {
assertScript '''
for (s in 'abc') assert s instanceof String
for (String s in 'abc') assert s instanceof String
'''
assertScript '''
for (char c in 'abc') assert c instanceof Character
for (Character c in 'abc') assert c instanceof Character
'''
}

// GROOVY-6123
void testForInLoopOnEnumeration() {
assertScript '''
@@ -21,7 +21,7 @@ package org.codehaus.groovy.classgen.asm.sc
import groovy.transform.stc.LoopsSTCTest

/**
* Unit tests for static type checking : miscellaneous tests.
* Unit tests for static compilation : loops.
*/
final class LoopsStaticCompileTest extends LoopsSTCTest implements StaticCompilationTestSupport {

0 comments on commit 5da51e1

Please sign in to comment.