@Override
  public SelLong assignOps(SelOp op, SelType rhs) {
    SelTypeUtil.checkTypeMatch(this.type(), rhs.type());
    long another = ((SelLong) rhs).val;
    switch (op) {
      case ASSIGN:
        this.val = another; // direct assignment
        return this;
      case ADD_ASSIGN:
        this.val += another;
        return this;
      case SUB_ASSIGN:
        this.val -= another;
        return this;
      case MUL_ASSIGN:
        this.val *= another;
        return this;
      case DIV_ASSIGN:
        this.val /= another;
        return this;
      case MOD_ASSIGN:
        this.val %= another;
        return this;
      default:
        throw new UnsupportedOperationException(
            "int/Integer/long/Long DO NOT support assignment operation " + op);
    }
  }
@Test
  public void testAssignOps() {
    SelType obj = SelLong.of(2);
    SelType res = orig.assignOps(SelOp.ASSIGN, obj);
    assertEquals("LONG: 2", res.type() + ": " + res);
    res = orig.assignOps(SelOp.ASSIGN, SelLong.of(3));
    assertEquals("LONG: 2", obj.type() + ": " + obj);
    assertEquals("LONG: 3", res.type() + ": " + res);
    res = orig.assignOps(SelOp.ADD_ASSIGN, obj);
    assertEquals("LONG: 5", res.type() + ": " + res);
    res = orig.assignOps(SelOp.SUB_ASSIGN, obj);
    assertEquals("LONG: 3", res.type() + ": " + res);
    res = orig.assignOps(SelOp.MUL_ASSIGN, obj);
    assertEquals("LONG: 6", res.type() + ": " + res);
    res = orig.assignOps(SelOp.DIV_ASSIGN, obj);
    assertEquals("LONG: 3", res.type() + ": " + res);
    res = orig.assignOps(SelOp.MOD_ASSIGN, obj);
    assertEquals("LONG: 1", res.type() + ": " + res);
  }