예제 #1
0
 public ClassNode box() {
   MethodVisitor mv = controller.getMethodVisitor();
   int size = stack.size();
   ClassNode type = stack.get(size - 1);
   if (ClassHelper.isPrimitiveType(type) && ClassHelper.VOID_TYPE != type) {
     ClassNode wrapper = ClassHelper.getWrapper(type);
     BytecodeHelper.doCastToWrappedType(mv, type, wrapper);
     type = wrapper;
   } // else nothing to box
   stack.set(size - 1, type);
   return type;
 }
예제 #2
0
  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);
  }
예제 #3
0
 /**
  * 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);
 }
예제 #4
0
  /** load the constant on the operand stack. */
  public void pushConstant(ConstantExpression expression) {
    MethodVisitor mv = controller.getMethodVisitor();
    Object value = expression.getValue();
    ClassNode origType = expression.getType().redirect();
    ClassNode type = ClassHelper.getUnwrapper(origType);
    boolean boxing = origType != type;
    boolean asPrimitive = boxing || ClassHelper.isPrimitiveType(type);

    if (value == null) {
      mv.visitInsn(ACONST_NULL);
    } else if (boxing && value instanceof Boolean) {
      // special path for boxed boolean
      Boolean bool = (Boolean) value;
      String text = bool ? "TRUE" : "FALSE";
      mv.visitFieldInsn(GETSTATIC, "java/lang/Boolean", text, "Ljava/lang/Boolean;");
      boxing = false;
      type = origType;
    } else if (asPrimitive) {
      pushPrimitiveConstant(mv, value, type);
    } else if (value instanceof BigDecimal) {
      String className = BytecodeHelper.getClassInternalName(value.getClass().getName());
      mv.visitTypeInsn(NEW, className);
      mv.visitInsn(DUP);
      mv.visitLdcInsn(value.toString());
      mv.visitMethodInsn(INVOKESPECIAL, className, "<init>", "(Ljava/lang/String;)V", false);
    } else if (value instanceof BigInteger) {
      String className = BytecodeHelper.getClassInternalName(value.getClass().getName());
      mv.visitTypeInsn(NEW, className);
      mv.visitInsn(DUP);
      mv.visitLdcInsn(value.toString());
      mv.visitMethodInsn(INVOKESPECIAL, className, "<init>", "(Ljava/lang/String;)V", false);
    } else if (value instanceof String) {
      mv.visitLdcInsn(value);
    } else {
      throw new ClassGeneratorException(
          "Cannot generate bytecode for constant: " + value + " of type: " + type.getName());
    }

    push(type);
    if (boxing) box();
  }
 public void visitCatchStatement(CatchStatement cs) {
   if (!(cs.getExceptionType().isDerivedFrom(ClassHelper.make(Throwable.class)))) {
     addError("Catch statement parameter type is not a subclass of Throwable.", cs);
   }
   super.visitCatchStatement(cs);
 }