Variable.java
package edu.udel.cis.vsl.tass.model.impl.variable;
import edu.udel.cis.vsl.tass.model.IF.SyntaxException;
import edu.udel.cis.vsl.tass.model.IF.expression.ExpressionIF;
import edu.udel.cis.vsl.tass.model.IF.type.ArrayTypeIF;
import edu.udel.cis.vsl.tass.model.IF.type.TypeIF;
import edu.udel.cis.vsl.tass.model.IF.type.TypeIF.TypeKind;
import edu.udel.cis.vsl.tass.model.IF.variable.FormalVariableIF;
import edu.udel.cis.vsl.tass.model.IF.variable.VariableIF;
import edu.udel.cis.vsl.tass.model.impl.scope.Scope;
import edu.udel.cis.vsl.tass.util.Source;
import edu.udel.cis.vsl.tass.util.TASSInternalException;
public class Variable implements VariableIF {
protected String name;
protected TypeIF type;
protected Scope scope;
protected int idInScope = -1;
protected Source sourceCode = null;
protected ExpressionIF[] dimensions = null;
protected ExpressionIF initializationExpression = null;
/** Allow null scope for certain variables, such as bound variables. */
public Variable(String name, TypeIF type, Scope scope) {
if (name == null)
throw new NullPointerException("Null variable name");
if (type == null)
throw new NullPointerException("Null type");
if (type.kind() == TypeKind.VOID) {
throw new RuntimeException("Variable type cannot be void.");
}
this.name = name;
this.type = type;
this.scope = scope;
}
@Override
public String name() {
return name;
}
@Override
public TypeIF type() {
return type;
}
@Override
public int idInScope() {
return idInScope;
}
public void setIdInScope(int id) {
this.idInScope = id;
}
@Override
public boolean equals(Object object) {
if (object instanceof Variable) {
Variable that = (Variable) object;
return name.equals(that.name) && scope.equals(that.scope);
}
return false;
}
@Override
public int hashCode() {
int result = name.hashCode() + scope.hashCode();
return result;
}
@Override
public String toString() {
return name;
}
@Override
public Source getSource() {
return sourceCode;
}
@Override
public void setSource(Source sourceCode) {
this.sourceCode = sourceCode;
}
@Override
public Scope scope() {
return scope;
}
@Override
public ExpressionIF[] dimensionExpressions() {
return dimensions;
}
/**
* Do the dimensions of dimensions need to add up to dimension of array? For
* now, yes.
*
* Are null entries allowed? For now, no.
*
* @param dimensions
* @throws SyntaxException
*/
public void setDimensions(ExpressionIF[] dimensions) throws SyntaxException {
if (type.kind() != TypeKind.ARRAY)
throw new SyntaxException(this,
"Cannot set dimensions of a non-array variable");
ArrayTypeIF arrayType = (ArrayTypeIF) type;
int dimension = arrayType.dimension();
int dimensionCount = 0;
int dimensionsLength = dimensions.length;
for (int i = 0; i < dimensionsLength; i++) {
ExpressionIF extent = dimensions[i];
if (extent == null) {
throw new SyntaxException(this, "array extent expression " + i
+ " is null");
}
TypeIF extentType = extent.type();
TypeKind extentTypeKind = extentType.kind();
dimensionCount++;
if (extentTypeKind == TypeKind.INTEGER) {
} else if (extentTypeKind == TypeKind.ARRAY) {
ArrayTypeIF extentArrayType = (ArrayTypeIF) extentType;
TypeIF baseType = extentArrayType.baseType();
if (baseType.kind() != TypeKind.INTEGER) {
throw new SyntaxException(this, "array extent expression "
+ i + " is array of non-integer base type: "
+ extent);
}
dimensionCount += extentArrayType.dimension();
} else {
throw new TASSInternalException(
"Unknown kind of array extent: " + extent);
}
}
if (dimensionCount != dimension) {
throw new SyntaxException(this,
"Dimensions array does not match dimension of variable "
+ this + ": " + dimensionCount + " != " + dimension);
}
this.dimensions = dimensions;
}
@Override
public String decl() {
String result;
if (type instanceof ArrayTypeIF && !(this instanceof FormalVariableIF)) {
if (dimensions == null)
throw new RuntimeException(this.sourceCode + ": "
+ "no dimensions given for this array variable");
ArrayTypeIF arrayType = (ArrayTypeIF) type;
result = arrayType.baseType().toString();
for (ExpressionIF dimension : dimensions) {
result += "[" + dimension + "]";
}
} else {
result = type().toString();
}
return result;
}
@Override
public ExpressionIF initializationExpression() {
return initializationExpression;
}
public void setInitializationExpression(ExpressionIF expression)
throws SyntaxException {
if (expression != null) {
TypeKind kind = type.kind();
TypeIF expressionType = expression.type();
if (!(type.equals(expressionType) || (kind == TypeKind.RATIONAL && expressionType
.kind() == TypeKind.INTEGER)))
throw new SyntaxException(expression,
"Type of initialization expression does not match type of v: "
+ expressionType + " vs. " + type);
this.initializationExpression = expression;
}
}
}