AssignmentStatement.java

package edu.udel.cis.vsl.tass.model.impl.statement;

import java.util.Collection;

import edu.udel.cis.vsl.tass.model.IF.ModelFactoryIF;
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.expression.LHSExpressionIF;
import edu.udel.cis.vsl.tass.model.IF.location.AssignmentLocationIF;
import edu.udel.cis.vsl.tass.model.IF.statement.AssignmentStatementIF;
import edu.udel.cis.vsl.tass.model.IF.type.TypeIF.TypeKind;
import edu.udel.cis.vsl.tass.model.IF.variable.SharedVariableIF;
import edu.udel.cis.vsl.tass.model.IF.variable.VariableIF;

public class AssignmentStatement extends Statement implements
		AssignmentStatementIF {

	private ASSIGNMENT_TYPE type;
	
	private LHSExpressionIF lhs;

	private ExpressionIF rhs;

	public AssignmentStatement(ModelFactoryIF factory,
			AssignmentLocationIF sourceLocation, LHSExpressionIF lhs,
			ExpressionIF rhs) throws SyntaxException {
		super(factory, sourceLocation, StatementKind.ASSIGNMENT);
		TypeKind kind = lhs.type().kind();

		type = ASSIGNMENT_TYPE.SIMPLE;
		if (!rhs.type().isSubtypeOf(lhs.type()))
			throw new SyntaxException(lhs,
					"Type mismatch: left-hand side of assignment has type "
							+ lhs.type() + " but right-hand side has type "
							+ rhs.type());
		if (!rhs.type().equals(lhs.type())) {
			rhs = factory.castExpression(lhs.type(), rhs);
		}
		factory.checkScope(rhs, sourceLocation.scope());
		factory.checkScope(lhs, sourceLocation.scope());
		if (kind != TypeKind.BOOLEAN && kind != TypeKind.INTEGER
				&& kind != TypeKind.POINTER && kind != TypeKind.RATIONAL
				&& kind != TypeKind.CHAR)
			throw new SyntaxException(lhs, "Illegal type used in assignment: "
					+ lhs.type());
		this.lhs = lhs;
		this.rhs = rhs;
	}
	
	public AssignmentStatement(ModelFactoryIF factory,
			AssignmentLocationIF sourceLocation, LHSExpressionIF lhs,
			ExpressionIF rhs, ASSIGNMENT_TYPE type) throws SyntaxException {
		super(factory, sourceLocation, StatementKind.ASSIGNMENT);
		TypeKind kind = lhs.type().kind();

		this.type = type;
		if (!rhs.type().isSubtypeOf(lhs.type()))
			throw new SyntaxException(lhs,
					"Type mismatch: left-hand side of assignment has type "
							+ lhs.type() + " but right-hand side has type "
							+ rhs.type());
		if (!rhs.type().equals(lhs.type())) {
			rhs = factory.castExpression(lhs.type(), rhs);
		}
		factory.checkScope(rhs, sourceLocation.scope());
		factory.checkScope(lhs, sourceLocation.scope());
		if (kind != TypeKind.BOOLEAN && kind != TypeKind.INTEGER
				&& kind != TypeKind.POINTER && kind != TypeKind.RATIONAL
				&& kind != TypeKind.CHAR)
			throw new SyntaxException(lhs, "Illegal type used in assignment: "
					+ lhs.type());
		this.lhs = lhs;
		this.rhs = rhs;
	}

	public LHSExpressionIF lhs() {
		return lhs;
	}

	public ExpressionIF rhs() {
		return rhs;
	}

	public String toString() {
		return lhs + " = " + rhs + ";";
	}

	public void complete() throws SyntaxException {
		Collection<SharedVariableIF> shared = process().model().scope()
				.properSharedVariables();

		super.complete();
		isLocal = true;
		for (VariableIF variable : lhs.freeVariables()) {
			if (variable instanceof SharedVariableIF
					&& shared.contains((SharedVariableIF) variable)) {
				isLocal = false;
				return;
			}
		}
		for (VariableIF variable : rhs.freeVariables()) {
			if (variable instanceof SharedVariableIF
					&& shared.contains((SharedVariableIF) variable)) {
				isLocal = false;
				return;
			}
		}

	}

	@Override
	public ASSIGNMENT_TYPE assignmentType() {
		return type;
	}

	@Override
	public void setAssignmentType(ASSIGNMENT_TYPE assignmentType) {
		type = assignmentType;
	}

}