/*
* xtc - The eXTensible Compiler
* Copyright (C) 2005-2007 Robert Grimm
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
* This program 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 for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
package xtc.type;
import java.io.IOException;
/**
* An array type. An array can either be of fixed or variable length,
* with a length of <code>-1</code> indicating that a fixed length
* array is incomplete.
*
* @author Robert Grimm
* @version $Revision: 1.40 $
*/
public class ArrayT extends DerivedT {
/** The element type. */
private Type type;
/** The flag for whether the array is variable length. */
private boolean varlength;
/** The length. */
private long length;
/**
* Create a new, incomplete array type.
*
* @param type The element type.
*/
public ArrayT(Type type) {
this(type, -1);
}
/**
* Create a new variable length array.
*
* @param type The element type.
* @param varlength The flag for whether this array is of variable
* length, which must be <code>true</code>.
*/
public ArrayT(Type type, boolean varlength) {
this.type = type;
this.varlength = varlength;
this.length = -1;
}
/**
* Create a new array type.
*
* @param type The element type.
* @param length The length.
*/
public ArrayT(Type type, long length) {
this.type = type;
this.varlength = false;
this.length = length;
}
/**
* Create a new array type.
*
* @param template The type whose annotations to copy.
* @param type The element type.
* @param varlength The flag for whether this array is variable.
* @param length The length.
*/
public ArrayT(Type template, Type type, boolean varlength, long length) {
super(template);
this.type = type;
this.varlength = varlength;
this.length = length;
}
public Type seal() {
if (! isSealed()) {
super.seal();
type.seal();
}
return this;
}
public ArrayT copy() {
return new ArrayT(this, type, varlength, length);
}
public Type.Tag tag() {
return Type.Tag.ARRAY;
}
public boolean isArray() {
return true;
}
public ArrayT toArray() {
return this;
}
/**
* Get the element type.
*
* @return The element type.
*/
public Type getType() {
return type;
}
/**
* Determine whether the array is of variable length.
*
* @return <code>true</code> if this array is variable length.
*/
public boolean isVarLength() {
return varlength;
}
/**
* Set the variable length flag.
*
* @param varlength The variable length flag.
* @throws IllegalStateException Signals that this type is sealed.
*/
public void setVarLength(boolean varlength) {
checkNotSealed();
this.varlength = varlength;
}
/**
* Determine whether this array has a length.
*
* @return <code>true</code> if this array has a length.
*/
public boolean hasLength() {
return -1 != length;
}
/**
* Get the length.
*
* @return The length or <code>-1</code> if this type is either of
* variable length or incomplete.
*/
public long getLength() {
return length;
}
/**
* Set the length.
*
* @param length The length.
* @throws IllegalStateException Signals that this type is sealed.
*/
public void setLength(long length) {
checkNotSealed();
this.length = length;
}
public int hashCode() {
return type.hashCode();
}
public boolean equals(Object o) {
if (! (o instanceof Type)) return false;
Type t = resolve(o);
if (this == t) return true;
if (! t.isArray()) return false;
ArrayT other = (ArrayT)t;
if (this.varlength != other.varlength) return false;
if (this.length != other.length) return false;
return this.type.equals(other.type);
}
public void write(Appendable out) throws IOException {
out.append("array(");
type.write(out);
if (varlength) {
out.append(", *");
} else if (-1 != length) {
out.append(", ");
out.append(Long.toString(length));
}
out.append(')');
}
}