public Object visit(RelationalExpression node) {
            node.setType(Type.BOOLEAN_TYPE);

            Token token = node.getOperator();
            int ID = token.getID();

            if (ID == Token.ISA) {
                return visitIsa(node);
            }

            Expression left = node.getLeftExpression();
            Expression right = node.getRightExpression();

            check(left);
            check(right);

            Type leftType = left.getType();
            Type rightType = right.getType();

            if (leftType != null && rightType != null) {
                Class<?> leftClass = leftType.getNaturalClass();
                Class<?> rightClass = rightType.getNaturalClass();

                Type type;
                if (ID == Token.EQ || ID == Token.NE) {
                    if (String.class.isAssignableFrom(leftClass)) {
                        type = leftType.toNullable();
                    }
                    else if (String.class.isAssignableFrom(rightClass)) {
                        type = rightType.toNullable();
                    }
                    else {
                        type = leftType.getCompatibleType(rightType);
                    }
                }
                else {
                    type = leftType.getCompatibleType(rightType);
                }

                if (type == null) {
                    type = Type.NULL_TYPE;
                }

                Class<?> clazz = type.getObjectClass();

                if (type.hasPrimitivePeer() &&
                    leftType.isNonNull() && rightType.isNonNull() &&
                    (leftType.isPrimitive() || leftType.hasPrimitivePeer()) &&
                    (rightType.isPrimitive() || rightType.hasPrimitivePeer()))
                {
                    // ensure primitive type is at least an int
                    leftType = rightType =
                        type.toPrimitive().getCompatibleType(Type.INT_TYPE);
                }
                else {
                    if (leftType.isNonNull()) {
                        leftType = type.toNonNull();
                        if (rightType.isNonNull()) {
                            rightType = leftType;
                        }
                        else {
                            rightType = type;
                        }
                    }
                    else {
                        leftType = type;
                        if (rightType.isNonNull()) {
                            rightType = type.toNonNull();
                        }
                        else {
                            rightType = type;
                        }
                    }
                }

                if (Number.class.equals(clazz)) {
                    // ensure primitive types are converted to at least an int
                    // otherwise, leave untouched to allow runtime checks
                    leftType = left.getType();
                    if (leftType.isPrimitive()) {
                        Type ctype = leftType.getCompatibleType(Type.INT_TYPE);
                        if (!leftType.equals(ctype)) {
                            left.convertTo(ctype);
                        }
                    }

                    rightType = right.getType();
                    if (rightType.isPrimitive()) {
                        Type ctype = rightType.getCompatibleType(Type.INT_TYPE);
                        if (!rightType.equals(ctype)) {
                            right.convertTo(ctype);
                        }
                    }
                }
                else if (ID == Token.EQ || ID == Token.NE ||
                         Comparable.class.isAssignableFrom(clazz) ||
                         Number.class.isAssignableFrom(clazz)) {

                    // Don't prefer cast; possibly perform string conversion.
                    left.convertTo(leftType, false);
                    right.convertTo(rightType, false);
                }
                else {
                    error("relationalexpression.type.mismatch",
                          token.getImage(), left.getType().getSimpleName(),
                          right.getType().getSimpleName(), node);
                }
            }

            node.setType(Type.BOOLEAN_TYPE);

            return null;
        }