ObjectLiteralExpression.java

package edu.udel.cis.vsl.tass.model.impl.expression.literal;

import edu.udel.cis.vsl.tass.model.IF.ModelFactoryIF;
import edu.udel.cis.vsl.tass.model.IF.expression.ExpressionIF;
import edu.udel.cis.vsl.tass.model.IF.expression.LiteralTypeIF;
import edu.udel.cis.vsl.tass.model.IF.expression.ObjectLiteralExpressionIF;
import edu.udel.cis.vsl.tass.model.IF.type.ArrayTypeIF;
import edu.udel.cis.vsl.tass.model.IF.type.RecordTypeIF;
import edu.udel.cis.vsl.tass.model.IF.type.TypeIF;

public class ObjectLiteralExpression extends LiteralExpression implements
		ObjectLiteralExpressionIF {

	private int objectLiteralID;

	private LiteralTypeIF literalType;

	public ObjectLiteralExpression(ModelFactoryIF factory,
			ExpressionIF[] value, TypeIF type, int literalId,
			int objectLiteralID) {
		super(factory, value, type, literalId);
		this.objectLiteralID = objectLiteralID;
		if (type instanceof ArrayTypeIF) {
			ArrayLiteralType join = new ArrayLiteralType((ArrayTypeIF) type,
					value.length);

			for (ExpressionIF element : value) {
				if (element instanceof ObjectLiteralExpressionIF) {
					computeJoin(join.elementLiteralType(),
							((ObjectLiteralExpressionIF) element).literalType());
				}
			}
			update(join, this);
		} else if (type instanceof RecordTypeIF) {
			RecordLiteralType join = new RecordLiteralType((RecordTypeIF) type);

			this.literalType = new RecordLiteralType((RecordTypeIF) type);
			computeJoin(join, literalType);
			update(join, this);
		} else {
			this.literalType = new LiteralType(type);
		}
	}

	private void computeJoin(LiteralTypeIF join, LiteralTypeIF literalType) {
		TypeIF type = join.type();

		assert type.equals(literalType.type());
		if (type instanceof ArrayTypeIF) {
			ArrayLiteralType arrayJoin = (ArrayLiteralType) join;
			ArrayLiteralType arrayLiteralType = (ArrayLiteralType) literalType;
			int extent = arrayLiteralType.extent();
			int maxExtent = arrayJoin.extent();

			if (extent > maxExtent) {
				arrayJoin.setExtent(extent);
			}
			computeJoin(arrayJoin.elementLiteralType(), arrayLiteralType
					.elementLiteralType());
		} else if (type instanceof RecordTypeIF) {
			RecordTypeIF recordType = (RecordTypeIF) type;
			RecordLiteralType recordJoin = (RecordLiteralType) join;
			RecordLiteralType recordLiteralType = (RecordLiteralType) literalType;
			LiteralTypeIF[] joinFieldTypes = recordJoin.fieldLiteralTypes();
			LiteralTypeIF[] literalFieldTypes = recordLiteralType
					.fieldLiteralTypes();
			int numFields = recordType.numFields();

			for (int i = 0; i < numFields; i++) {
				computeJoin(joinFieldTypes[i], literalFieldTypes[i]);
			}
		} else {
			return;
		}
	}

	/** Impose the new type on the given literal expression, recursively. */
	void update(LiteralTypeIF newLiteralType, ObjectLiteralExpression expression) {
		TypeIF type = newLiteralType.type();

		assert type.equals(expression.type());
		expression.setLiteralType(newLiteralType);
		if (type instanceof ArrayTypeIF) {
			ArrayLiteralType arrayLiteralType = (ArrayLiteralType) newLiteralType;
			LiteralTypeIF elementLiteralType = arrayLiteralType
					.elementLiteralType();

			for (ExpressionIF child : expression.value()) {
				if (child instanceof ObjectLiteralExpression) {
					update(elementLiteralType, (ObjectLiteralExpression) child);
				}
			}
		} else if (type instanceof RecordTypeIF) {
			RecordLiteralType recordLiteralType = (RecordLiteralType) newLiteralType;
			LiteralTypeIF[] fieldLiteralTypes = recordLiteralType
					.fieldLiteralTypes();
			int numFields = fieldLiteralTypes.length;
			ExpressionIF[] children = expression.value();

			for (int i = 0; i < numFields; i++) {
				ExpressionIF child = children[i];

				if (child instanceof ObjectLiteralExpression) {
					update(fieldLiteralTypes[i],
							(ObjectLiteralExpression) child);
				}
			}
		}
	}

	void setLiteralType(LiteralTypeIF literalType) {
		this.literalType = literalType;
	}

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

	@Override
	public ExpressionIF[] value() {
		return (ExpressionIF[]) super.value();
	}

	@Override
	public LiteralTypeIF literalType() {
		return literalType;
	}

	public String toString() {
		ExpressionIF[] elements = value();
		boolean flag = true;
		String result = "{";

		for (ExpressionIF element : elements) {
			if (flag)
				flag = false;
			else
				result += ", ";
			if (element != null)
				result += element.toString();
		}
		result += "}";
		return result;
	}
}