/*
* This file is part of the X10 project (http://x10-lang.org).
*
* This file is licensed to You under the Eclipse Public License (EPL);
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.opensource.org/licenses/eclipse-1.0.php
*
* This file was originally derived from the Polyglot extensible compiler framework.
*
* (C) Copyright 2000-2007 Polyglot project group, Cornell University
* (C) Copyright IBM Corporation 2007-2012.
*/
package polyglot.types.reflect;
import java.io.*;
/**
* A Constant is used to represent an item in the constant pool of a class.
*
* @author Nate Nystrom
* (<a href="mailto:nystrom@cs.purdue.edu">nystrom@cs.purdue.edu</a>)
*/
public class Constant
{
protected int tag;
protected Object value;
/**
* Constant tag for class types.
* This is used to reference other classes, such as the superclass,
* and is used by the checkcast and instanceof instructions.
* The Fieldref, Methodref and InterfaceMethodref constant types
* refer to this constant type.
*/
public static final byte CLASS = 7;
/**
* Constant tag for field references.
* This is used to reference a field in (possibly) another class.
* The getfield, putfield, getstatic, and putstatic instructions use
* this constant type.
*/
public static final byte FIELD_REF = 9;
/**
* Constant tag for method references.
* This is used to reference a method in (possibly) another class.
* The invokevirtual, invokespecial, and invokestatic instructions use
* this constant type.
*/
public static final byte METHOD_REF = 10;
/**
* Constant tag for java.lang.String constants.
* The actual string value is stored indirectly in a Utf8 constant.
*/
public static final byte STRING = 8;
/**
* Constant tag for int, short, byte, char, and boolean constants.
*/
public static final byte INTEGER = 3;
/**
* Constant tag for float constants.
*/
public static final byte FLOAT = 4;
/**
* Constant tag for long constants.
*/
public static final byte LONG = 5;
/**
* Constant tag for double constants.
*/
public static final byte DOUBLE = 6;
/**
* Constant tag for method references.
* This is used to reference a method in an interface.
* The invokeinterface instruction uses this constant type.
*/
public static final byte INTERFACE_METHOD_REF = 11;
/**
* Constant tag for holding the name and type of a field or method.
* The Fieldref, Methodref and InterfaceMethodref constant types
* refer to this constant type.
*/
public static final byte NAME_AND_TYPE = 12;
/**
* Constant tag for holding the a UTF8 format string.
* The string is used to hold the name and type descriptor for
* NameandType constants, the class name for Class constants,
* the string value for String constants.
*/
public static final byte UTF8 = 1;
/**
* @param tag
* The constant's tag.
* @param value
* The constant's value.
*/
Constant(final int tag, final Object value)
{
this.tag = tag;
this.value = value;
}
/**
* Get the tag of the constant.
*
* @return
* The tag.
*/
final int tag()
{
return tag;
}
/**
* Get the value of the constant.
*
* @return
* The value.
*/
public final Object value()
{
return value;
}
/**
* Hash the constant.
*
* @return
* The hash code.
*/
public int hashCode()
{
switch (tag) {
case CLASS:
case STRING:
case INTEGER:
case FLOAT:
case LONG:
case DOUBLE:
case UTF8:
return tag ^ value.hashCode();
case FIELD_REF:
case METHOD_REF:
case INTERFACE_METHOD_REF:
case NAME_AND_TYPE:
return tag ^ ((int[]) value)[0] ^ ((int[]) value)[1];
}
return tag;
}
/**
* Check if an object is equal to this constant.
*
* @param other
* The object to compare against.
* @return
* true if equal, false if not.
*/
public boolean equals(Object other)
{
if (! (other instanceof Constant)) {
return false;
}
Constant c = (Constant) other;
if (tag != c.tag) {
return false;
}
switch (tag) {
case CLASS:
case STRING:
case INTEGER:
case FLOAT:
case LONG:
case DOUBLE:
case UTF8:
return value.equals(c.value);
case FIELD_REF:
case METHOD_REF:
case INTERFACE_METHOD_REF:
case NAME_AND_TYPE:
return ((int[]) value)[0] == ((int[]) c.value)[0] &&
((int[]) value)[1] == ((int[]) c.value)[1];
}
return false;
}
}