in src/main/java/org/codehaus/groovy/classgen/AsmClassGenerator.java [1666:1795]
public void visitArrayExpression(final ArrayExpression expression) {
MethodVisitor mv = controller.getMethodVisitor();
CompileStack compileStack = controller.getCompileStack();
OperandStack operandStack = controller.getOperandStack();
ClassNode arrayType = expression.getType();
ClassNode elementType = arrayType.getComponentType();
int size = 0, dimensions = 0;
if (expression.hasInitializer()) {
if (containsSpreadExpression(expression)) {
despreadList(expression.getExpressions(), false);
if (elementType.equals(ClassHelper.OBJECT_TYPE)){
operandStack.push(arrayType);
return;
}
mv.visitInsn(DUP); // Object[] from despreadList
mv.visitInsn(ARRAYLENGTH);
mv.visitInsn(DUP); // store value count
operandStack.push(ClassHelper.int_TYPE);
size = -compileStack.defineTemporaryVariable("value$count", ClassHelper.int_TYPE, true);
} else {
size = expression.getExpressions().size();
BytecodeHelper.pushConstant(mv, size);
}
// stack: ..., size
} else {
for (final Expression sizeExpr : expression.getSizeExpression()) {
if (sizeExpr == ConstantExpression.EMPTY_EXPRESSION) break;
dimensions += 1;
sizeExpr.visit(this);
operandStack.doGroovyCast(ClassHelper.int_TYPE);
}
operandStack.remove(dimensions);
// stack: ..., size (one per dimension)
}
int storeIns = AASTORE;
if (!elementType.isArray() || expression.hasInitializer()) {
if (isPrimitiveType(elementType)) {
int primType = 0;
if (isPrimitiveBoolean(elementType)) {
primType = T_BOOLEAN;
storeIns = BASTORE;
} else if (isPrimitiveChar(elementType)) {
primType = T_CHAR;
storeIns = CASTORE;
} else if (isPrimitiveFloat(elementType)) {
primType = T_FLOAT;
storeIns = FASTORE;
} else if (isPrimitiveDouble(elementType)) {
primType = T_DOUBLE;
storeIns = DASTORE;
} else if (isPrimitiveByte(elementType)) {
primType = T_BYTE;
storeIns = BASTORE;
} else if (isPrimitiveShort(elementType)) {
primType = T_SHORT;
storeIns = SASTORE;
} else if (isPrimitiveInt(elementType)) {
primType = T_INT;
storeIns = IASTORE;
} else if (isPrimitiveLong(elementType)) {
primType = T_LONG;
storeIns = LASTORE;
}
mv.visitIntInsn(NEWARRAY, primType);
} else {
mv.visitTypeInsn(ANEWARRAY, BytecodeHelper.getClassInternalName(elementType));
maybeInnerClassEntry(elementType);
}
} else {
mv.visitMultiANewArrayInsn(BytecodeHelper.getTypeDescription(arrayType), dimensions);
}
// stack: ..., array
if (size >= 0) {
for (int i = 0; i < size; i += 1) {
mv.visitInsn(DUP); // array ref
BytecodeHelper.pushConstant(mv, i);
Optional.ofNullable(expression.getExpression(i))
.orElse(ConstantExpression.NULL)
.visit(this);
operandStack.doGroovyCast(elementType);
mv.visitInsn(storeIns);
operandStack.remove(1);
}
} else {
// stack: ..., source, target
Label top = new Label();
mv.visitLabel(top);
{
final int idx = -size;
mv.visitIincInsn(idx, -1);
mv.visitInsn(DUP2);
mv.visitInsn(SWAP);
// stack: ..., target, source
mv.visitVarInsn(ILOAD, idx);
// stack: ..., target, source, index
mv.visitInsn(AALOAD);
// stack: ..., target, value
operandStack.push(ClassHelper.OBJECT_TYPE);
operandStack.doGroovyCast(elementType);
mv.visitVarInsn(ILOAD, idx);
// stack: ..., target, value, index
operandStack.push(ClassHelper.int_TYPE);
operandStack.swap();
// stack: ..., target, index, value
mv.visitInsn(storeIns);
operandStack.remove(2);
// stack: ...
mv.visitVarInsn(ILOAD, idx);
mv.visitJumpInsn(IFNE, top);
compileStack.removeVar(idx);
}
// stack: ..., source, target
mv.visitInsn(SWAP);
// stack: ..., target, source
mv.visitInsn(POP);
// stack: ..., target
}
operandStack.push(arrayType);
}