CommonArrayType.java
package edu.udel.cis.vsl.abc.ast.type.common;
import java.io.PrintStream;
import java.util.Map;
import edu.udel.cis.vsl.abc.ast.node.IF.expression.ExpressionNode;
import edu.udel.cis.vsl.abc.ast.type.IF.ArrayType;
import edu.udel.cis.vsl.abc.ast.type.IF.ObjectType;
import edu.udel.cis.vsl.abc.ast.type.IF.Type;
import edu.udel.cis.vsl.abc.ast.value.IF.IntegerValue;
public class CommonArrayType extends CommonObjectType implements ArrayType {
private final static int classCode = CommonArrayType.class.hashCode();
private ObjectType elementType;
private ExpressionNode variableSize;
private IntegerValue constantSize;
private boolean unspecifiedVariableLength;
private int dimension = 0;
/**
* Creates a new array type with given element type and value for
* unspecifiedVariableLength.
*
* @param elementType
* a complete object type
* @param unspecifiedVariableLength
* is this an array declared with "*" for the size expression?
*/
public CommonArrayType(ObjectType elementType,
boolean unspecifiedVariableLength) {
super(TypeKind.ARRAY);
this.elementType = elementType;
this.variableSize = null;
this.constantSize = null;
this.unspecifiedVariableLength = unspecifiedVariableLength;
}
/**
* Creates a new complete array type in which the extent does not have a
* constant value.
*
* @param elementType
* a complete object type
* @param variableSize
* the expression specifying the length of the array
*/
public CommonArrayType(ObjectType elementType, ExpressionNode variableSize) {
super(TypeKind.ARRAY);
this.elementType = elementType;
this.variableSize = variableSize;
this.constantSize = null;
this.unspecifiedVariableLength = false;
}
/**
* Creates a new complete array type in which the extent has a known
* constant value.
*
* @param elementType
* complete object type
* @param constantSize
* the constant obtained by evaluating the extent expression
*/
public CommonArrayType(ObjectType elementType, IntegerValue constantSize) {
super(TypeKind.ARRAY);
this.elementType = elementType;
this.variableSize = null;
this.constantSize = constantSize;
this.unspecifiedVariableLength = false;
}
@Override
public boolean isComplete() {
return variableSize != null || constantSize != null
|| unspecifiedVariableLength;
}
@Override
public ObjectType getElementType() {
return elementType;
}
@Override
public ExpressionNode getVariableSize() {
return variableSize;
}
@Override
public boolean isVariableLengthArrayType() {
return unspecifiedVariableLength || variableSize != null
|| !elementType.hasKnownConstantSize();
}
@Override
public boolean hasUnspecifiedVariableLength() {
return this.unspecifiedVariableLength;
}
@Override
public boolean isVariablyModified() {
return isVariableLengthArrayType() || elementType.isVariablyModified();
}
@Override
public IntegerValue getConstantSize() {
return constantSize;
}
@Override
public int hashCode() {
int result = classCode ^ ((CommonType) elementType).hashCode();
if (constantSize != null)
result ^= constantSize.hashCode();
else if (variableSize != null)
result ^= variableSize.hashCode();
if (unspecifiedVariableLength)
result ^= 172830823; // random int
return result;
}
@Override
public boolean equals(Object obj) {
if (obj instanceof CommonArrayType) {
CommonArrayType that = (CommonArrayType) obj;
if (!elementType.equals(that.elementType))
return false;
if (constantSize != null) {
if (that.constantSize == null)
return false;
if (!constantSize.equals(that.constantSize))
return false;
} else {
if (that.constantSize != null)
return false;
if (variableSize != null) {
if (that.variableSize == null)
return false;
if (!variableSize.equals(that.variableSize))
return false;
} else {
if (that.variableSize != null)
return false;
}
}
return unspecifiedVariableLength == that.unspecifiedVariableLength;
}
return false;
}
private boolean equivalentTo(Type other, Map<TypeKey, Type> seen) {
if (other instanceof CommonArrayType) {
CommonArrayType that = (CommonArrayType) other;
if (!((CommonType) elementType).similar(that.elementType, true,
seen))
return false;
if (constantSize != null) {
if (that.constantSize == null)
return false;
if (!constantSize.equals(that.constantSize))
return false;
} else {
if (that.constantSize != null)
return false;
if (variableSize != null) {
if (that.variableSize == null)
return false;
if (!variableSize.equals(that.variableSize))
return false;
} else {
if (that.variableSize != null)
return false;
}
}
return unspecifiedVariableLength == that.unspecifiedVariableLength;
}
return false;
}
private boolean compatibleWith(Type type, Map<TypeKey, Type> seen) {
if (type instanceof CommonArrayType) {
CommonArrayType that = (CommonArrayType) type;
if (!((CommonType) elementType).similar(that.elementType, false,
seen))
return false;
if (constantSize != null && that.constantSize != null
&& !constantSize.equals(that.constantSize))
return false;
return true;
}
return false;
}
@Override
public String toString() {
String result = "ArrayType[elementType=" + elementType;
if (variableSize != null)
result += ", size=" + variableSize;
if (constantSize != null)
result += ", size=" + constantSize;
if (unspecifiedVariableLength)
result += ", unspecifiedVariableLength";
result += "]";
return result;
}
@Override
public void print(String prefix, PrintStream out, boolean abbrv) {
out.println("Array");
out.print(prefix + "| elementType = ");
elementType.print(prefix + "| ", out, true);
out.println();
out.print(prefix + "| size = ");
if (constantSize != null)
out.print(constantSize);
else if (variableSize != null)
out.print(variableSize);
else if (unspecifiedVariableLength)
out.print("unspecified variable length");
}
@Override
public boolean isScalar() {
return false;
}
@Override
protected boolean similar(Type other, boolean equivalent,
Map<TypeKey, Type> seen) {
return equivalent ? equivalentTo(other, seen) : compatibleWith(other,
seen);
}
@Override
public boolean isConstantQualified() {
return this.elementType.isConstantQualified();
}
@Override
public int getDimension() {
if (dimension == 0) {
ObjectType type = this;
while (type.kind() == TypeKind.ARRAY) {
dimension++;
type = ((ArrayType) type).getElementType();
}
}
return dimension;
}
}