@Override protected void assignToArray( Expression orig, Expression receiver, Expression index, Expression rhsValueLoader) { ClassNode current = getController().getClassNode(); ClassNode arrayType = getController().getTypeChooser().resolveType(receiver, current); ClassNode arrayComponentType = arrayType.getComponentType(); int operationType = getOperandType(arrayComponentType); BinaryExpressionWriter bew = binExpWriter[operationType]; AsmClassGenerator acg = getController().getAcg(); if (bew.arraySet(true) && arrayType.isArray()) { OperandStack operandStack = getController().getOperandStack(); // load the array receiver.visit(acg); operandStack.doGroovyCast(arrayType); // load index index.visit(acg); operandStack.doGroovyCast(int_TYPE); // load rhs rhsValueLoader.visit(acg); operandStack.doGroovyCast(arrayComponentType); // store value in array bew.arraySet(false); // load return value && correct operand stack stack operandStack.remove(3); rhsValueLoader.visit(acg); } else { super.assignToArray(orig, receiver, index, rhsValueLoader); } }
private boolean doAssignmentToArray(BinaryExpression binExp) { if (!isAssignmentToArray(binExp)) return false; // we need to handle only assignment to arrays combined with an operation // special here. e.g x[a] += b int operation = removeAssignment(binExp.getOperation().getType()); ClassNode current = getController().getClassNode(); Expression leftExp = binExp.getLeftExpression(); ClassNode leftType = getController().getTypeChooser().resolveType(leftExp, current); Expression rightExp = binExp.getRightExpression(); ClassNode rightType = getController().getTypeChooser().resolveType(rightExp, current); int operationType = getOperandType(leftType); BinaryExpressionWriter bew = binExpWriter[operationType]; boolean simulationSuccess = bew.arrayGet(LEFT_SQUARE_BRACKET, true); simulationSuccess = simulationSuccess && bew.write(operation, true); simulationSuccess = simulationSuccess && bew.arraySet(true); if (!simulationSuccess) return false; AsmClassGenerator acg = getController().getAcg(); OperandStack operandStack = getController().getOperandStack(); CompileStack compileStack = getController().getCompileStack(); // for x[a] += b we have the structure: // x = left(left(binExp))), b = right(binExp), a = right(left(binExp))) // for array set we need these values on stack: array, index, right // for array get we need these values on stack: array, index // to eval the expression we need x[a] = x[a]+b // -> arraySet(x,a, x[a]+b) // -> arraySet(x,a, arrayGet(x,a,b)) // --> x,a, x,a, b as operands // --> load x, load a, DUP2, call arrayGet, load b, call operation,call arraySet // since we cannot DUP2 here easily we will save the subscript and DUP x // --> sub=a, load x, DUP, load sub, call arrayGet, load b, call operation, load sub, call // arraySet BinaryExpression arrayWithSubscript = (BinaryExpression) leftExp; Expression subscript = arrayWithSubscript.getRightExpression(); // load array index: sub=a [load x, DUP, load sub, call arrayGet, load b, call operation, load // sub, call arraySet] subscript.visit(acg); operandStack.doGroovyCast(int_TYPE); int subscriptValueId = compileStack.defineTemporaryVariable("$sub", ClassHelper.int_TYPE, true); // load array: load x and DUP [load sub, call arrayGet, load b, call operation, load sub, call // arraySet] arrayWithSubscript.getLeftExpression().visit(acg); operandStack.doGroovyCast(leftType.makeArray()); operandStack.dup(); // array get: load sub, call arrayGet [load b, call operation, load sub, call arraySet] operandStack.load(ClassHelper.int_TYPE, subscriptValueId); bew.arrayGet(LEFT_SQUARE_BRACKET, false); operandStack.replace(leftType, 2); // complete rhs: load b, call operation [load sub, call arraySet] binExp.getRightExpression().visit(acg); if (!(bew instanceof BinaryObjectExpressionHelper)) { // in primopts we convert to the left type for supported binary operations operandStack.doGroovyCast(leftType); } bew.write(operation, false); // let us save that value for the return operandStack.dup(); int resultValueId = compileStack.defineTemporaryVariable("$result", rightType, true); // array set: load sub, call arraySet [] operandStack.load(ClassHelper.int_TYPE, subscriptValueId); operandStack.swap(); bew.arraySet(false); operandStack.remove(3); // 3 operands, the array, the index and the value! // load return value operandStack.load(rightType, resultValueId); // cleanup compileStack.removeVar(resultValueId); compileStack.removeVar(subscriptValueId); return true; }