@Override
  public SelType binaryOps(SelOp op, SelType rhs) {
    if (rhs.type() == SelTypes.NULL) {
      if (op == SelOp.EQUAL || op == SelOp.NOT_EQUAL) {
        return rhs.binaryOps(op, this);
      } else {
        throw new UnsupportedOperationException(
            this.type() + " DO NOT support " + op + " for rhs with NULL value");
      }
    }

    if (rhs.type() == SelTypes.STRING) {
      return SelString.of(String.valueOf(this.val)).binaryOps(op, rhs);
    }

    double another = ((Number) rhs.getInternalVal()).doubleValue();
    switch (op) {
      case EQUAL:
        return SelBoolean.of(this.val == another);
      case NOT_EQUAL:
        return SelBoolean.of(this.val != another);
      case LT:
        return SelBoolean.of(this.val < another);
      case GT:
        return SelBoolean.of(this.val > another);
      case LTE:
        return SelBoolean.of(this.val <= another);
      case GTE:
        return SelBoolean.of(this.val >= another);
      case ADD:
        return new SelDouble(this.val + another);
      case SUB:
        return new SelDouble(this.val - another);
      case MUL:
        return new SelDouble(this.val * another);
      case DIV:
        return new SelDouble(this.val / another);
      case MOD:
        return new SelDouble(this.val % another);
      case PLUS:
        return new SelDouble(this.val);
      case MINUS:
        return new SelDouble(-this.val);
      default:
        throw new UnsupportedOperationException(
            "float/Float/double/Doubles DO NOT support expression operation " + op);
    }
  }
@Test(expected = UnsupportedOperationException.class)
  public void testInvalidBinaryOpType() {
    one.binaryOps(SelOp.ADD, SelType.NULL);
  }