private void jitStringConcat(Expression left, Expression right) {
   invokeConstructor(StringBuilder.class);
   jitExpression(left, String.class);
   invokeVirtual(StringBuilder.class, "append", StringBuilder.class, left.getType());
   jitExpression(right, String.class);
   invokeVirtual(StringBuilder.class, "append", StringBuilder.class, right.getType());
   invokeVirtual(StringBuilder.class, "toString", String.class);
 }
    private void jitInstanceof(SingleCondition singleCondition) {
      Class<?> value = (Class<?>) ((FixedExpression) singleCondition.getRight()).getValue();
      String internalClassName = internalName(value);

      Expression left = singleCondition.getLeft();
      Class<?> leftType =
          isDeclarationExpression(left) ? convertFromPrimitiveType(left.getType()) : left.getType();
      jitExpression(left, leftType);

      mv.visitTypeInsn(INSTANCEOF, internalClassName);
    }
 private void ensureNotNullArgs(Expression exp, Label nullArg) {
   if (exp instanceof FixedExpression) {
     if (((FixedExpression) exp).canBeNull()) {
       mv.visitJumpInsn(GOTO, nullArg);
     }
   } else if (exp instanceof EvaluatedExpression) {
     if (!exp.getType().isPrimitive()) {
       jitEvaluatedExpression((EvaluatedExpression) exp, true, Object.class);
       mv.visitJumpInsn(IFNULL, nullArg);
     }
   } else if (exp instanceof VariableExpression) {
     if (!exp.getType().isPrimitive()) {
       jitVariableExpression((VariableExpression) exp);
       mv.visitJumpInsn(IFNULL, nullArg);
     }
   } else if (exp instanceof AritmeticExpression) {
     ensureNotNullInAritmeticExpression((AritmeticExpression) exp, nullArg);
   }
 }
 private Class<?> jitExpression(Expression exp, Class<?> requiredClass) {
   if (exp instanceof FixedExpression) {
     push(((FixedExpression) exp).getValue(), requiredClass);
     return exp.getType();
   } else if (exp instanceof EvaluatedExpression) {
     return jitEvaluatedExpression((EvaluatedExpression) exp, true, Object.class);
   } else if (exp instanceof VariableExpression) {
     return jitVariableExpression((VariableExpression) exp);
   } else if (exp instanceof AritmeticExpression) {
     return jitAritmeticExpression((AritmeticExpression) exp);
   } else if (exp instanceof ArrayCreationExpression) {
     return jitArrayCreationExpression((ArrayCreationExpression) exp);
   } else if (exp instanceof CastExpression) {
     return jitCastExpression((CastExpression) exp);
   } else {
     throw new RuntimeException("Unknown expression: " + exp);
   }
 }
    private void jitPrimitiveBinary(
        SingleCondition singleCondition, Expression left, Expression right, Class<?> type) {
      if (isFixed(right) && right.canBeNull()) {
        // a primitive cannot be null
        mv.visitInsn(singleCondition.getOperation() == BooleanOperator.NE ? ICONST_1 : ICONST_0);
        return;
      }
      Label nullArg = new Label();
      ensureNotNullArgs(left, right, nullArg);

      jitExpression(left, type);
      castExpressionResultToPrimitive(left, type);
      jitExpression(right, type);
      castExpressionResultToPrimitive(right, type);
      jitPrimitiveOperation(singleCondition.getOperation(), type);
      Label nonNullArg = new Label();
      mv.visitJumpInsn(GOTO, nonNullArg);

      mv.visitLabel(nullArg);
      mv.visitInsn(ICONST_0);
      mv.visitLabel(nonNullArg);
    }
    private void jitBinary(SingleCondition singleCondition) {
      Expression left = singleCondition.getLeft();
      Expression right = singleCondition.getRight();
      Class<?> commonType =
          singleCondition.getOperation().needsSameType()
              ? findCommonClass(
                  left.getType(), !left.canBeNull(), right.getType(), !right.canBeNull())
              : null;

      if (commonType == Object.class && singleCondition.getOperation().isComparison()) {
        commonType = Comparable.class;
      }

      if (commonType != null && commonType.isPrimitive()) {
        jitPrimitiveBinary(singleCondition, left, right, commonType);
      } else {
        jitObjectBinary(singleCondition, left, right, commonType);
      }
    }
 private void jitExpressionToPrimitiveType(Expression expression, Class<?> primitiveType) {
   jitExpression(expression, primitiveType);
   if (!isFixed(expression)) {
     cast(expression.getType(), primitiveType);
   }
 }
 private Class<?> jitExpression(Expression exp) {
   return jitExpression(exp, exp.getType());
 }
    private void jitObjectBinary(
        SingleCondition singleCondition, Expression left, Expression right, Class<?> type) {
      Class<?> leftType =
          isDeclarationExpression(left) ? convertFromPrimitiveType(left.getType()) : left.getType();
      Class<?> rightType =
          isDeclarationExpression(right)
              ? convertFromPrimitiveType(right.getType())
              : right.getType();

      jitExpression(left, type != null ? type : leftType);
      if (isDeclarationExpression(left) && left.getType().isPrimitive()) {
        castFromPrimitive(left.getType());
      }
      store(LEFT_OPERAND, leftType);

      jitExpression(right, type != null ? type : rightType);
      if (isDeclarationExpression(right) && right.getType().isPrimitive()) {
        castFromPrimitive(right.getType());
      }
      store(RIGHT_OPERAND, rightType);

      Label shortcutEvaluation = new Label();
      BooleanOperator operation = singleCondition.getOperation();
      prepareLeftOperand(operation, type, leftType, rightType, shortcutEvaluation);
      prepareRightOperand(right, type, rightType, shortcutEvaluation);

      load(LEFT_OPERAND);
      load(RIGHT_OPERAND);

      switch (operation) {
        case CONTAINS:
          invokeStatic(
              EvaluatorHelper.class,
              "contains",
              boolean.class,
              Object.class,
              rightType.isPrimitive() ? rightType : Object.class);
          break;
        case MATCHES:
          invokeVirtual(type, "matches", boolean.class, String.class);
          break;
        case SOUNDSLIKE:
          invokeStatic(
              EvaluatorHelper.class, "soundslike", boolean.class, String.class, String.class);
          break;
        default:
          if (operation.isEquality()) {
            if (type.isInterface()) {
              invokeInterface(type, "equals", boolean.class, Object.class);
            } else {
              invokeVirtual(type, "equals", boolean.class, Object.class);
            }
            if (operation == BooleanOperator.NE) {
              singleCondition.toggleNegation();
            }
          } else {
            if (type.isInterface()) {
              invokeInterface(
                  type, "compareTo", int.class, type == Comparable.class ? Object.class : type);
            } else {
              invokeVirtual(type, "compareTo", int.class, type);
            }
            mv.visitInsn(ICONST_0);
            jitPrimitiveOperation(operation, int.class);
          }
      }

      mv.visitLabel(shortcutEvaluation);
    }
 private void castExpressionResultToPrimitive(Expression expression, Class<?> type) {
   if (!isFixed(expression)) {
     cast(expression.getType(), type);
   }
 }