IfStatementBuilder ifLeftIsNull = ifStatementBuilder(context)
.comment("if left wasNull...")
.condition(new Block(context).getVariable("wasNull"));
LabelNode end = new LabelNode("end");
ifLeftIsNull.ifTrue(new Block(context)
.comment("clear the null flag, pop left value off stack, and push left null flag on the stack (true)")
.putVariable("wasNull", false)
.pop(leftType.getJavaType()) // discard left value
.push(true));
LabelNode leftIsFalse = new LabelNode("leftIsFalse");
ifLeftIsNull.ifFalse(new Block(context)
.comment("if left is true, push true, and goto end")
.ifFalseGoto(leftIsFalse)
.push(true)
.gotoLabel(end)
.comment("left was false; push left null flag on the stack (false)")
.visitLabel(leftIsFalse)
.push(false));
block.append(ifLeftIsNull.build());
// At this point we know the left expression was either NULL or FALSE. The stack contains a single boolean
// value for this expression which indicates if the left value was NULL.
// eval right!
block.append(right);
IfStatementBuilder ifRightIsNull = ifStatementBuilder(context)
.comment("if right wasNull...")
.condition(new Block(context).getVariable("wasNull"));
// this leaves a single boolean on the stack which is ignored since the value in NULL
ifRightIsNull.ifTrue(new Block(context)
.comment("right was null, pop the right value off the stack; wasNull flag remains set to TRUE")
.pop(rightType.getJavaType()));
LabelNode rightIsTrue = new LabelNode("rightIsTrue");
ifRightIsNull.ifFalse(new Block(context)
.comment("if right is true, pop left null flag off stack, push true and goto end")
.ifFalseGoto(rightIsTrue)
.pop(boolean.class)
.push(true)