/* * Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package com.sun.max.vm.value; import java.util.*; /** * Constants denoting comparison operations that can be performed between pairs of {@linkplain Value values} of the same * {@linkplain Value#kind() kind}. The comparison operations fall into one of these categories: * <dl> * <dt>Equality</dt> * <dd>Comparisons between two values for equality or inequality.</dd> * <dt>Arithmetic</dt> * <dd>Comparisons to determine if the first value is greater than, equal to or less than the second value. The * semantics of these comparisons with respect to signedness depends on the kinds of the values. For example, comparing * two {@code char} values makes an unsigned comparison where as comparing two {@code int} values is a signed * comparison. These comparisons can only be applied to value kinds that have well defined semantics for arithmetic * comparison.</dd> * <dt>Unsigned arithmetic</dt> * <dd>Comparisons to determine if the first value is greater than, equal to or less than the second value. These * comparisons always treat the values as unsigned and can only be applied to value kinds that have well defined * semantics for unsigned arithmetic comparison.</dd> * </dl> */ public enum ValueComparator { EQUAL { @Override public final ValueComparator complement() { return NOT_EQUAL; } @Override final boolean compare(Value left, Value right) { return left.equals(right); } }, NOT_EQUAL { @Override public final ValueComparator complement() { return EQUAL; } @Override final boolean compare(Value left, Value right) { return !left.equals(right); } }, LESS_THAN { @Override public final ValueComparator complement() { return GREATER_EQUAL; } @Override final boolean compare(Value left, Value right) { return left.compareTo(right) < 0; } }, LESS_EQUAL { @Override public final ValueComparator complement() { return GREATER_THAN; } @Override final boolean compare(Value left, Value right) { return left.compareTo(right) <= 0; } }, GREATER_EQUAL { @Override public final ValueComparator complement() { return LESS_THAN; } @Override final boolean compare(Value left, Value right) { return left.compareTo(right) >= 0; } }, GREATER_THAN { @Override public final ValueComparator complement() { return LESS_EQUAL; } @Override final boolean compare(Value left, Value right) { return left.compareTo(right) > 0; } }, UNSIGNED_GREATER_THAN { @Override public final ValueComparator complement() { return UNSIGNED_LESS_EQUAL; } @Override final boolean compare(Value left, Value right) { return left.unsignedCompareTo(right) > 0; } }, UNSIGNED_LESS_EQUAL { @Override public final ValueComparator complement() { return UNSIGNED_GREATER_THAN; } @Override final boolean compare(Value left, Value right) { return left.unsignedCompareTo(right) <= 0; } }, UNSIGNED_GREATER_EQUAL { @Override public final ValueComparator complement() { return UNSIGNED_LESS_THAN; } @Override final boolean compare(Value left, Value right) { return left.unsignedCompareTo(right) >= 0; } }, UNSIGNED_LESS_THAN { @Override public final ValueComparator complement() { return UNSIGNED_GREATER_EQUAL; } @Override final boolean compare(Value left, Value right) { return left.unsignedCompareTo(right) < 0; } }; public static final List<ValueComparator> VALUES = Arrays.asList(values()); public abstract ValueComparator complement(); /** * Evaluates the relationship between two values of the same kind. * * @param left the left value * @param right the right value * @return {@code true} if relationship denoted by this comparator holds between {@code left} and {@code right}, * {@code false} otherwise * @throws IllegalArgumentException if {@code left}'s {@linkplain Value#kind() kind} is not the same as {@code right}'s * kind or the semantics of comparison for the values' kind is undefined */ public final boolean evaluate(Value left, Value right) { if (left.kind() != right.kind()) { throw new IllegalArgumentException("Cannot perform unsigned comparison between values of different kinds: " + left.kind() + " and " + right.kind()); } return compare(left, right); } abstract boolean compare(Value left, Value right); public String symbol() { switch (this) { case EQUAL: return "=="; case GREATER_EQUAL: return ">="; case GREATER_THAN: return ">"; case LESS_EQUAL: return "<="; case LESS_THAN: return "<"; case NOT_EQUAL: return "!="; default: return toString(); } } }