.build();
ResidualEvaluator resEval = new ResidualEvaluator(spec, or(or(
and(lessThan("dateint", 20170815), greaterThan("dateint", 20170801)),
and(equal("dateint", 20170815), lessThan("hour", 12))),
Expression residual = resEval.residualFor(Row.of(20170815));
UnboundPredicate<?> unbound = assertAndUnwrapUnbound(residual);
Assert.assertEquals("Residual should be hour < 12", LT, unbound.op());
residual = resEval.residualFor(Row.of(20170801));
unbound = assertAndUnwrapUnbound(residual);
Assert.assertEquals("Residual should be hour > 11", GT, unbound.op());
residual = resEval.residualFor(Row.of(20170812));
Assert.assertEquals("Residual should be alwaysTrue", alwaysTrue(), residual);
residual = resEval.residualFor(Row.of(20170817));
Assert.assertEquals("Residual should be alwaysFalse", alwaysFalse(), residual);