@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);
    }
  }
  @Override
  protected void evaluateCompareExpression(
      final MethodCaller compareMethod, BinaryExpression binExp) {
    ClassNode current = getController().getClassNode();
    TypeChooser typeChooser = getController().getTypeChooser();

    Expression leftExp = binExp.getLeftExpression();
    ClassNode leftType = typeChooser.resolveType(leftExp, current);
    Expression rightExp = binExp.getRightExpression();
    ClassNode rightType = typeChooser.resolveType(rightExp, current);

    if (!doPrimitiveCompare(leftType, rightType, binExp)) {
      super.evaluateCompareExpression(compareMethod, binExp);
    }
  }
 @Override
 protected void writePostOrPrefixMethod(
     int op, String method, Expression expression, Expression orig) {
   ClassNode type =
       getController().getTypeChooser().resolveType(orig, getController().getClassNode());
   int operationType = getOperandType(type);
   BinaryExpressionWriter bew = binExpWriter[operationType];
   if (bew.writePostOrPrefixMethod(op, true)) {
     OperandStack operandStack = getController().getOperandStack();
     // at this point the receiver will be already on the stack
     operandStack.doGroovyCast(type);
     bew.writePostOrPrefixMethod(op, false);
     operandStack.replace(bew.getNormalOpResultType());
   } else {
     super.writePostOrPrefixMethod(op, method, expression, orig);
   }
 }
 @Override
 protected void evaluateBinaryExpressionWithAssignment(String method, BinaryExpression binExp) {
   if (doAssignmentToArray(binExp)) return;
   if (doAssignmentToLocalVariable(method, binExp)) return;
   super.evaluateBinaryExpressionWithAssignment(method, binExp);
 }
  @Override
  protected void evaluateBinaryExpression(final String message, BinaryExpression binExp) {
    int operation = removeAssignment(binExp.getOperation().getType());
    ClassNode current = getController().getClassNode();

    Expression leftExp = binExp.getLeftExpression();
    ClassNode leftTypeOrig = getController().getTypeChooser().resolveType(leftExp, current);
    ClassNode leftType = leftTypeOrig;
    Expression rightExp = binExp.getRightExpression();
    ClassNode rightType = getController().getTypeChooser().resolveType(rightExp, current);

    AsmClassGenerator acg = getController().getAcg();
    OperandStack os = getController().getOperandStack();

    if (operation == LEFT_SQUARE_BRACKET) {
      leftType = leftTypeOrig.getComponentType();
      int operationType = getOperandType(leftType);
      BinaryExpressionWriter bew = binExpWriter[operationType];
      if (leftTypeOrig.isArray() && isIntCastableType(rightExp) && bew.arrayGet(operation, true)) {
        leftExp.visit(acg);
        os.doGroovyCast(leftTypeOrig);
        rightExp.visit(acg);
        os.doGroovyCast(int_TYPE);
        bew.arrayGet(operation, false);
        os.replace(bew.getArrayGetResultType(), 2);
      } else {
        super.evaluateBinaryExpression(message, binExp);
      }
    } else if (operation == DIVIDE) {
      int operationType =
          getOperandType(getController().getTypeChooser().resolveType(binExp, current));
      BinaryExpressionWriter bew = binExpWriter[operationType];
      if (bew.writeDivision(true)) {
        leftExp.visit(acg);
        os.doGroovyCast(bew.getDevisionOpResultType());
        rightExp.visit(acg);
        os.doGroovyCast(bew.getDevisionOpResultType());
        bew.writeDivision(false);
      } else {
        super.evaluateBinaryExpression(message, binExp);
      }
    } else {
      int operationType = getOperandConversionType(leftType, rightType);
      BinaryExpressionWriter bew = binExpWriter[operationType];

      if (isShiftOperation(operation)
          && isIntCastableType(rightExp)
          && bew.write(operation, true)) {
        leftExp.visit(acg);
        os.doGroovyCast(bew.getNormalOpResultType());
        rightExp.visit(acg);
        os.doGroovyCast(int_TYPE);
        bew.write(operation, false);
      } else if (bew.write(operation, true)) {
        leftExp.visit(acg);
        os.doGroovyCast(bew.getNormalOpResultType());
        rightExp.visit(acg);
        os.doGroovyCast(bew.getNormalOpResultType());
        bew.write(operation, false);
      } else {
        super.evaluateBinaryExpression(message, binExp);
      }
    }
  }