private void generateBranch(Expression expr, Label label,
                                    boolean whenTrue, boolean invert) {

            // get the simple state for handling whenTrue
            // if this is an inversion (ie: not operation), then we use the
            // opposite.  Note that this does not apply for compound statements
            // such as truthful expressions which requires the aggregate to be
            // the opposite rather than its individual parts
            boolean _whenTrue = (invert ? !whenTrue : whenTrue);

            if (expr instanceof Logical) {
                // What follows is something that the visitor design pattern
                // solves, but I would need to make a special visitor
                // interface that operates only on logicals that also accepts
                // labels and "whenTrue" flags.

                if (expr instanceof RelationalExpression) {
                    generateBranch((RelationalExpression)expr, label, _whenTrue);
                }
                else if (expr instanceof NotExpression) {
                    generateBranch((NotExpression)expr, label, _whenTrue);
                }
                else if (expr instanceof AndExpression) {
                    generateBranch((AndExpression)expr, label, _whenTrue);
                }
                else if (expr instanceof OrExpression) {
                    generateBranch((OrExpression)expr, label, _whenTrue);
                }
            }
            else {
                // Generate branch in the same special way for all
                // non-logical expressions.
                Type type = expr.getType();
                if (expr.isValueKnown()) {
                    Object value = expr.getValue();
                    if (value == null && !_whenTrue) {
                        mBuilder.branch(label);
                    }
                    else if (value instanceof Truthful) {
                        boolean isTrue = ((Truthful) value).isTrue();
                        if ((!isTrue && !_whenTrue) || (isTrue && _whenTrue)) {
                            mBuilder.branch(label);
                        }
                    }
                    else if (value instanceof Boolean) {
                        boolean isTrue = ((Boolean) value).booleanValue();
                        if ((!isTrue && !_whenTrue) || (isTrue && _whenTrue)) {
                            mBuilder.branch(label);
                        }
                    }
                    else if (value instanceof Number) {
                        boolean valid =
                            WrapperTypeConversionUtil.isValid((Number) value);
                        if ((!valid && !_whenTrue) || (valid && _whenTrue)) {
                            mBuilder.branch(label);
                        }
                    }
                    else if (value instanceof String) {
                        int length = ((String) value).length();
                        if ((length == 0 && !_whenTrue) ||
                            (length != 0 && _whenTrue)) {
                            mBuilder.branch(label);
                        }
                    }
                    else if (value != null && value.getClass().isArray()) {
                        int length = Array.getLength(value);
                        if ((length == 0 && !_whenTrue) ||
                            (length != 0 && _whenTrue)) {
                            mBuilder.branch(label);
                        }
                    }
                    else if (value instanceof Collection) {
                        int length = ((Collection<?>) value).size();
                        if ((length == 0 && !_whenTrue) ||
                            (length != 0 && _whenTrue)) {
                            mBuilder.branch(label);
                        }
                    }
                    else if (value instanceof Map) {
                        int length = ((Map<?, ?>) value).size();
                        if ((length == 0 && !_whenTrue) ||
                            (length != 0 && _whenTrue)) {
                            mBuilder.branch(label);
                        }
                    }
                    else if (value != null && _whenTrue) {
                        mBuilder.branch(label);
                    }
                }
                else if (type == null) {
                    // unknown type, just perform straight comparison
                    generate(expr);
                    mBuilder.ifZeroComparisonBranch(label, _whenTrue ? "!=" : "==");
                }
                else if (type.isPrimitive()) {
                    generate(expr);
                    Class<?> clazz = type.getNaturalClass();
                    if (long.class.equals(clazz)) {
                           mBuilder.loadConstant(0L);
                           mBuilder.math(Opcode.LCMP);
                           mBuilder.ifZeroComparisonBranch(label, _whenTrue ? "!=" : "==");
                    }
                    else if (float.class.equals(clazz)) {
                        mBuilder.loadConstant(0.0f);
                        mBuilder.math(Opcode.FCMPG);
                        mBuilder.ifZeroComparisonBranch(label, _whenTrue ? "!=" : "==");
                    }
                    else if (double.class.equals(clazz)) {
                        mBuilder.loadConstant(0.0);
                        mBuilder.math(Opcode.DCMPG);
                        mBuilder.ifZeroComparisonBranch(label, _whenTrue ? "!=" : "==");
                    }
                    else {
                        // standard type, just perform straight comparison
                        mBuilder.ifZeroComparisonBranch(label, _whenTrue ? "!=" : "==");
                    }
                }
                else {
                    generate(expr);

                    // load the variable for variable refs to avoid duplicating
                    // local variables
                    Variable var = null;
                    if (expr instanceof VariableRef) {
                        var = ((VariableRef) expr).getVariable();
                    }

                    // create a temp local variable for non-variable refs
                    // as long as we are nullable such that we must make two
                    // checks (null and truth)
                    LocalVariable local = null;
                    if (var == null && type.isNullable()) {
                        TypeDesc desc = makeDesc(type);
                        if (desc.isDoubleWord()) { mBuilder.dup2(); }
                        else { mBuilder.dup(); }

                        local = mBuilder.createLocalVariable(null, desc);
                        mBuilder.storeLocal(local);
                    }

                    // create a branch to go to in order to evaluate the truth
                    // check after the null check...only valid if we need the
                    // null check
                    Label branch = null;
                    if (_whenTrue && type.isNullable()) {
                        branch = mBuilder.createLabel();
                    }

                    // test for null (false value)
                    if (type.isNullable()) {
                        mBuilder.ifNullBranch(_whenTrue ? branch : label, true);

                        // load the data again to do further testing after the
                        // null check...if we have a local variable from
                        // earlier, load it otherwise, if we have a reference
                        // load that instead
                        if (local != null) { mBuilder.loadLocal(local); }
                        else if (var != null) { loadFromVariable(var); }
                    }

                    // get the associated class for comparison
                    Class<?> clazz = type.getNaturalClass();

                    // handle truthful values
                    if (Truthful.class.isAssignableFrom(clazz)) {
                        mBuilder.invoke(getMethod(Truthful.class, "isTrue"));
                        mBuilder.ifZeroComparisonBranch(label,
                            _whenTrue ? "!=" : "==");
                    }

                    // handle boolean values
                    else if (Boolean.class.isAssignableFrom(clazz)) {
                        mBuilder.invoke(getMethod(Boolean.class, "booleanValue"));
                        mBuilder.ifZeroComparisonBranch(label,
                            _whenTrue ? "!=" : "==");
                    }

                    // handle numeric values
                    else if (Number.class.isAssignableFrom(clazz)) {
                        Type ctype =
                            type.getCompatibleType(Type.INT_TYPE).toPrimitive();

                        // handle types that are primitive and known
                        if (ctype.isPrimitive()) {
                            if (!type.equals(ctype)) {
                                typeConvertEnd(type, ctype, false);
                            }

                            generateZeroComparison(label,
                                _whenTrue ? "!=" : "==", ctype);
                        }

                        // otherwise, test at runtime to evaluate
                        else {
                            Method method = getMethod
                            (
                                WrapperTypeConversionUtil.class,
                                "isValid", Number.class
                            );

                            mBuilder.invoke(method);
                            mBuilder.ifZeroComparisonBranch(label,
                                _whenTrue ? "!=" : "==");
                        }
                    }

                    // handle string values
                    else if (String.class.isAssignableFrom(clazz)) {
                        mBuilder.invoke(getMethod(String.class, "length"));
                        mBuilder.ifZeroComparisonBranch(label,
                            _whenTrue ? "!=" : "==");
                    }

                    // handle array values
                    else if (clazz.isArray()) {
                        mBuilder.arrayLength();
                        mBuilder.ifZeroComparisonBranch(label,
                            _whenTrue ? "!=" : "==");
                    }

                    // handle collection values
                    else if (Collection.class.isAssignableFrom(clazz)) {
                        mBuilder.invoke(getMethod(Collection.class, "size"));
                        mBuilder.ifZeroComparisonBranch(label,
                            _whenTrue ? "!=" : "==");
                    }

                    // handle map values
                    else if (Map.class.isAssignableFrom(clazz)) {
                        mBuilder.invoke(getMethod(Map.class, "size"));
                        mBuilder.ifZeroComparisonBranch(label,
                            _whenTrue ? "!=" : "==");
                    }

                    // any other case, just pop last value (assume true)
                    // if expected true, then branch
                    else {
                        // warn("truthful.object.expression", expr);

                        mBuilder.pop();
                        if (_whenTrue) {
                            mBuilder.branch(label);
                        }
                    }

                    // set the location to jump the null check to for when the
                    // request was to jump to the actual label if only true
                    // this branch is placed here as the next lines of code
                    // are the false aspect.  If the null check fails, it is
                    // not true and thus it jump here.
                    if (branch != null) {
                        branch.setLocation();
                    }
                }
            }
        }