CommonAtomicLockAssignStatement.java

package dev.civl.mc.model.common.statement;

import java.util.HashSet;
import java.util.Set;

import dev.civl.mc.model.IF.CIVLSource;
import dev.civl.mc.model.IF.Scope;
import dev.civl.mc.model.IF.expression.Expression;
import dev.civl.mc.model.IF.expression.LHSExpression;
import dev.civl.mc.model.IF.location.Location;
import dev.civl.mc.model.IF.statement.AtomicLockAssignStatement;
import dev.civl.mc.model.IF.variable.Variable;

/**
 * When translating an $atomic block, we need to create a noop statement at the
 * beginning and at the end of the block. In order to have more information
 * about the transitions, we create this class to extend
 * {@link CommonNoopStatement}. Currently, there is a field {@link #enter} to
 * denote if the statement is
 * <ol>
 * <li>entering an $atomic block; or</li>
 * <li>leaving an $atomic block.</li>
 * </ol>
 * 
 * @author Manchun Zheng (zmanchun)
 * 
 */
public class CommonAtomicLockAssignStatement extends CommonAssignStatement
		implements
			AtomicLockAssignStatement {

	/* *************************** Instance Fields ************************* */

	/**
	 * Denote if this statement is
	 * <ol>
	 * <li>enter == true: entering an $atomic or</li>
	 * <li>enter == false: leaving an $atomic block.</li>
	 * </ol>
	 */
	private boolean enter;

	/**
	 * The external variables which are accessed in the atomic region, or null.
	 */
	private Set<Variable> variables = null;

	/* **************************** Constructors *************************** */

	/**
	 * 
	 * @param civlSource
	 *            The CIVL source of this statement. More information in
	 *            {@link CIVLSource}.
	 * @param source
	 *            The source location of this goto statement
	 * @param atomicKind
	 *            The atomic kind of this statement
	 */
	public CommonAtomicLockAssignStatement(CIVLSource civlSource, Scope hscope,
			Scope lscope, Location source, Expression guard, boolean isEntering,
			LHSExpression lhs, Expression rhs) {
		super(civlSource, hscope, lscope, source, guard, lhs, rhs, false);
		this.enter = isEntering;
	}

	/* ************************* Methods from Object *********************** */

	@Override
	public String toString() {
		String result = super.toString();

		if (enter) {
			result = "ENTER_ATOMIC (" + result + ", atomicCount++; vars=";
			if (variables == null)
				result += "unknown";
			else
				result += variables.toString();
			result += ")";
		} else
			result = "LEAVE_ATOMIC (" + result + ", atomicCount--)";
		return result;
	}

	public void setVariables(Set<Variable> variables) {
		this.variables = variables;
	}

	@Override
	public Set<Variable> getVariables() {
		return variables;
	}

	@Override
	public Set<Variable> variableAddressedOf(Scope scope) {
		return null;
	}

	@Override
	public Set<Variable> variableAddressedOf() {
		return null;
	}

	@Override
	public void calculateDerefs() {
		this.hasDerefs = false;
	}

	@Override
	public boolean enterAtomic() {
		return this.enter;
	}

	@Override
	public boolean leaveAtomic() {
		return !this.enter;
	}

	@Override
	public boolean equals(Object obj) {
		if (super.equals(obj)) {
			if (obj instanceof CommonAtomicLockAssignStatement) {
				CommonAtomicLockAssignStatement other = (CommonAtomicLockAssignStatement) obj;

				return other.enter == enter;
			}
		}
		return false;
	}

	@Override
	public Set<Variable> freeVariables() {
		return new HashSet<>();
	}
}