RecordValue.java

package edu.udel.cis.vsl.tass.dynamic.impl.value;

import java.util.Arrays;

import edu.udel.cis.vsl.tass.dynamic.IF.type.RecordValueTypeIF;
import edu.udel.cis.vsl.tass.dynamic.IF.value.RecordValueIF;
import edu.udel.cis.vsl.tass.dynamic.IF.value.ValueIF;
import edu.udel.cis.vsl.tass.dynamic.impl.type.ValueTypeFactory;
import edu.udel.cis.vsl.tass.model.IF.type.RecordTypeIF;
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.morph.Morphic;

public class RecordValue extends Value implements RecordValueIF {

	private static int classHashCode = RecordValue.class.hashCode();

	private ValueIF[] elements;

	public RecordValue(ValueIF[] elements, RecordValueTypeIF valueType) {
		super(valueType);

		TypeIF type = valueType.type();
		RecordTypeIF recordType;
		int numFields;

		if (type.kind() != TypeKind.RECORD) {
			throw new IllegalArgumentException("Expected record type:\n"
					+ valueType);
		}
		recordType = (RecordTypeIF) type;
		numFields = recordType.numFields();
		if (numFields != elements.length)
			throw new RuntimeException(
					"Number of elements does not match number of fields:\n"
							+ elements.length + "\n" + elements + "\n"
							+ numFields + "\n" + recordType);
		// to do: check compatibility of each element with field type
		this.elements = elements;
	}

	@Override
	protected int computeHashCode() {
		return super.computeHashCode() + classHashCode
				+ Arrays.hashCode(elements);
	}

	public ValueIF[] elements() {
		return elements;
	}

	@Override
	public ValueIF element(int i) {
		return elements[i];
	}

	public int numElements() {
		return valueType().type().numFields();
	}

	@Override
	public void setElement(int index, ValueIF value) {
		assert !isCommitted();
		elements[index] = value;
	}

	@Override
	public RecordValueTypeIF valueType() {
		return (RecordValueTypeIF) super.valueType();
	}

	@Override
	protected boolean computeEquals(Morphic component) {
		if (!super.computeEquals(component))
			return false;
		if (component instanceof RecordValue) {
			RecordValue that = (RecordValue) component;

			return Arrays.equals(elements, that.elements);
		}
		return false;
	}

	@Override
	public String toString() {
		String result = "[";

		for (int i = 0; i < elements.length; i++) {
			if (i > 0)
				result += ", ";
			result += elements[i];
		}
		result += "]";
		return result;
	}

	@Override
	protected void commitChildren() {
		super.commitChildren();
		for (ValueIF element : elements)
			element.commit();
	}

	@Override
	protected void canonicalizeChildren(ValueFactory valueFactory,
			ValueTypeFactory typeFactory) {
		super.canonicalizeChildren(valueFactory, typeFactory);

		int numElements = elements.length;

		for (int i = 0; i < numElements; i++) {
			Value element = (Value) elements[i];

			if (element != null && !element.isCanonic())
				elements[i] = valueFactory.canonic(element);
		}
	}
}