@Override
  public SelBoolean binaryOps(SelOp op, SelType rhs) {
    if (rhs.type() == SelTypes.NULL && (op == SelOp.EQUAL || op == SelOp.NOT_EQUAL)) {
      return (SelBoolean) rhs.binaryOps(op, this);
    }

    SelTypeUtil.checkTypeMatch(this.type(), rhs.type());
    boolean another = ((SelBoolean) rhs).booleanVal();
    switch (op) {
      case AND:
        return SelBoolean.of(val && another);
      case OR:
        return SelBoolean.of(val || another);
      case EQUAL:
        return SelBoolean.of(val == another);
      case NOT_EQUAL:
        return SelBoolean.of(val != another);
      case NOT:
        return SelBoolean.of(!val);
      default:
        throw new UnsupportedOperationException(
            this.type() + " DO NOT support expression operation " + op);
    }
  }
@Test
  public void testBinaryOps() {
    assertFalse(one.binaryOps(SelOp.AND, another).booleanVal());
    assertTrue(one.binaryOps(SelOp.OR, another).booleanVal());
    assertFalse(one.binaryOps(SelOp.EQUAL, another).booleanVal());
    assertTrue(one.binaryOps(SelOp.NOT_EQUAL, another).booleanVal());
    assertFalse(one.binaryOps(SelOp.NOT, another).booleanVal());
    assertFalse(one.binaryOps(SelOp.EQUAL, SelType.NULL).booleanVal());
    assertTrue(one.binaryOps(SelOp.NOT_EQUAL, SelType.NULL).booleanVal());
  }