private void doConvertAndCast(ClassNode targetType, boolean coerce) {
    int size = stack.size();
    throwExceptionForNoStackElement(size, targetType, coerce);

    ClassNode top = stack.get(size - 1);
    targetType = targetType.redirect();
    if (targetType == top) return;

    if (coerce) {
      controller.getInvocationWriter().coerce(top, targetType);
      return;
    }

    boolean primTarget = ClassHelper.isPrimitiveType(targetType);
    boolean primTop = ClassHelper.isPrimitiveType(top);

    if (primTop && primTarget) {
      // here we box and unbox to get the goal type
      if (convertPrimitive(top, targetType)) {
        replace(targetType);
        return;
      }
      box();
    } else if (primTop) {
      // top is primitive, target is not
      // so box and do groovy cast
      controller.getInvocationWriter().castToNonPrimitiveIfNecessary(top, targetType);
    } else if (primTarget) {
      // top is not primitive so unbox
      // leave that BH#doCast later
    } else {
      controller.getInvocationWriter().castToNonPrimitiveIfNecessary(top, targetType);
    }

    MethodVisitor mv = controller.getMethodVisitor();
    if (primTarget
        && !ClassHelper.boolean_TYPE.equals(targetType)
        && !primTop
        && ClassHelper.getWrapper(targetType).equals(top)) {
      BytecodeHelper.doCastToPrimitive(mv, top, targetType);
    } else {
      top = stack.get(size - 1);
      if (!WideningCategories.implementsInterfaceOrSubclassOf(top, targetType)) {
        BytecodeHelper.doCast(mv, targetType);
      }
    }
    replace(targetType);
  }
 /**
  * ensure last marked parameter on the stack is a primitive boolean if mark==stack size, we assume
  * an empty expression or statement. was used and we will use the value given in emptyDefault as
  * boolean if mark==stack.size()-1 the top element will be cast to boolean using Groovy truth. In
  * other cases we throw a GroovyBugError
  */
 public void castToBool(int mark, boolean emptyDefault) {
   int size = stack.size();
   MethodVisitor mv = controller.getMethodVisitor();
   if (mark == size) {
     // no element, so use emptyDefault
     if (emptyDefault) {
       mv.visitIntInsn(BIPUSH, 1);
     } else {
       mv.visitIntInsn(BIPUSH, 0);
     }
     stack.add(null);
   } else if (mark == stack.size() - 1) {
     ClassNode last = stack.get(size - 1);
     // nothing to do in that case
     if (last == ClassHelper.boolean_TYPE) return;
     // not a primitive type, so call booleanUnbox
     if (!ClassHelper.isPrimitiveType(last)) {
       controller.getInvocationWriter().castNonPrimitiveToBool(last);
     } else {
       primitive2b(mv, last);
     }
   } else {
     throw new GroovyBugError(
         "operand stack contains " + stack.size() + " elements, but we expected only " + mark);
   }
   stack.set(mark, ClassHelper.boolean_TYPE);
 }
  protected void evaluateBinaryExpression(String message, BinaryExpression binExp) {
    CompileStack compileStack = controller.getCompileStack();

    Expression receiver = binExp.getLeftExpression();
    Expression arguments = binExp.getRightExpression();

    // ensure VariableArguments are read, not stored
    compileStack.pushLHS(false);
    controller.getInvocationWriter().makeSingleArgumentCall(receiver, message, arguments);
    compileStack.popLHS();
  }
 protected void assignToArray(
     Expression parent, Expression receiver, Expression index, Expression rhsValueLoader) {
   // let's replace this assignment to a subscript operator with a
   // method call
   // e.g. x[5] = 10
   // -> (x, [], 5), =, 10
   // -> methodCall(x, "putAt", [5, 10])
   ArgumentListExpression ae = new ArgumentListExpression(index, rhsValueLoader);
   controller
       .getInvocationWriter()
       .makeCall(
           parent,
           receiver,
           new ConstantExpression("putAt"),
           ae,
           InvocationWriter.invokeMethod,
           false,
           false,
           false);
   controller.getOperandStack().pop();
   // return value of assignment
   rhsValueLoader.visit(controller.getAcg());
 }
  @Override
  public void makeGroovyObjectGetPropertySite(
      final Expression receiver,
      final String methodName,
      final boolean safe,
      final boolean implicitThis) {
    TypeChooser typeChooser = controller.getTypeChooser();
    ClassNode classNode = controller.getClassNode();
    ClassNode receiverType = typeChooser.resolveType(receiver, classNode);
    if (receiver instanceof VariableExpression
        && ((VariableExpression) receiver).isThisExpression()
        && !controller.isInClosure()) {
      receiverType = classNode;
    }

    String property = methodName;
    if (implicitThis) {
      if (controller.getInvocationWriter() instanceof StaticInvocationWriter) {
        MethodCallExpression currentCall =
            ((StaticInvocationWriter) controller.getInvocationWriter()).getCurrentCall();
        if (currentCall != null
            && currentCall.getNodeMetaData(StaticTypesMarker.IMPLICIT_RECEIVER) != null) {
          property = (String) currentCall.getNodeMetaData(StaticTypesMarker.IMPLICIT_RECEIVER);
          String[] props = property.split("\\.");
          BytecodeExpression thisLoader =
              new BytecodeExpression() {
                @Override
                public void visit(final MethodVisitor mv) {
                  mv.visitVarInsn(ALOAD, 0); // load this
                }
              };
          thisLoader.setType(CLOSURE_TYPE);
          Expression pexp =
              new PropertyExpression(thisLoader, new ConstantExpression(props[0]), safe);
          for (int i = 1, propsLength = props.length; i < propsLength; i++) {
            final String prop = props[i];
            pexp.putNodeMetaData(StaticTypesMarker.INFERRED_TYPE, CLOSURE_TYPE);
            pexp = new PropertyExpression(pexp, prop);
          }
          pexp.visit(controller.getAcg());
          return;
        }
      }
    }

    if (makeGetPropertyWithGetter(receiver, receiverType, property, safe, implicitThis)) return;
    if (makeGetField(
        receiver,
        receiverType,
        property,
        implicitThis,
        samePackages(receiverType.getPackageName(), classNode.getPackageName()))) return;

    MethodCallExpression call =
        new MethodCallExpression(
            receiver, "getProperty", new ArgumentListExpression(new ConstantExpression(property)));
    call.setImplicitThis(implicitThis);
    call.setSafe(safe);
    call.setMethodTarget(GROOVYOBJECT_GETPROPERTY_METHOD);
    call.visit(controller.getAcg());
    return;
  }