BoundVariable.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.TypeIF;
import edu.udel.cis.vsl.tass.model.IF.variable.BoundVariableIF;
import edu.udel.cis.vsl.tass.model.impl.scope.BoundScope;

/**
 * A bound variable, as used for example in "forall (x) ...".
 * 
 * Unlike other variables, a bound variable may have null scope until it is
 * completed. For this reason, the scope is not used in the equals or hashCode
 * methods. Instead, each bound variable has a globally unique id, the
 * boundVariableId, which is used to determine equality and hashCode.
 */
public class BoundVariable extends Variable implements BoundVariableIF {

	/**
	 * A unique hash code for this class, used to compute the hash code for each
	 * instance.
	 */
	private final static int classHashCode = BoundVariable.class.hashCode();

	/**
	 * An ID which distinguishes this instance of BoundVariable, unique among
	 * all bound variables created by the same model factory.
	 */
	private int boundVariableId = -1;

	public BoundVariable(String name, TypeIF type, BoundScope scope, int id) {
		super(name, type, scope);
		this.boundVariableId = id;
	}

	public void setInitializationExpression(ExpressionIF expression)
			throws SyntaxException {
		throw new SyntaxException(this,
				"Bound variables cannot be assigned an initial value");
	}

	@Override
	public int boundVariableId() {
		return boundVariableId;
	}

	/** The scope to which this bound variable belongs. */
	@Override
	public BoundScope scope() {
		return (BoundScope) super.scope();
	}

	/**
	 * Overrides the standard equals method in Variable class to use
	 * boundVariableId instead of scope and name. This is because scope may be
	 * null for bound variables, at least at certain times.
	 */
	@Override
	public boolean equals(Object object) {
		if (object instanceof BoundVariable) {
			return boundVariableId == ((BoundVariable) object).boundVariableId;
		}
		return false;
	}

	@Override
	public int hashCode() {
		return classHashCode + boundVariableId;
	}

}