All Downloads are FREE. Search and download functionalities are using the official Maven repository.

it.unive.lisa.analysis.combination.NonRelationalValueCartesianProduct Maven / Gradle / Ivy

The newest version!
package it.unive.lisa.analysis.combination;

import it.unive.lisa.analysis.SemanticException;
import it.unive.lisa.analysis.SemanticOracle;
import it.unive.lisa.analysis.lattices.Satisfiability;
import it.unive.lisa.analysis.nonrelational.value.BaseNonRelationalValueDomain;
import it.unive.lisa.analysis.nonrelational.value.NonRelationalValueDomain;
import it.unive.lisa.analysis.nonrelational.value.ValueEnvironment;
import it.unive.lisa.program.cfg.ProgramPoint;
import it.unive.lisa.symbolic.SymbolicExpression;
import it.unive.lisa.symbolic.value.Identifier;
import it.unive.lisa.symbolic.value.ValueExpression;
import it.unive.lisa.util.representation.ListRepresentation;
import it.unive.lisa.util.representation.StructuredRepresentation;
import java.util.Map.Entry;

/**
 * A generic Cartesian product abstract domain between two non-communicating
 * {@link NonRelationalValueDomain}s (i.e., no exchange of information between
 * the abstract domains), assigning the same {@link Identifier}s and handling
 * instances of the same {@link SymbolicExpression}s.
 * 
 * @author Luca Negrini
 *
 * @param   the concrete type of the Cartesian product
 * @param  the concrete instance of the left-hand side abstract domain of
 *                 the Cartesian product
 * @param  the concrete instance of the right-hand side abstract domain of
 *                 the Cartesian product
 */
public abstract class NonRelationalValueCartesianProduct,
		T1 extends NonRelationalValueDomain,
		T2 extends NonRelationalValueDomain>
		implements
		BaseNonRelationalValueDomain {

	/**
	 * The left-hand side abstract domain.
	 */
	public final T1 left;

	/**
	 * The right-hand side abstract domain.
	 */
	public final T2 right;

	/**
	 * Builds the Cartesian product abstract domain.
	 * 
	 * @param left  the left-hand side of the Cartesian product
	 * @param right the right-hand side of the Cartesian product
	 */
	public NonRelationalValueCartesianProduct(
			T1 left,
			T2 right) {
		this.left = left;
		this.right = right;
	}

	/**
	 * Builds a new instance of Cartesian product.
	 * 
	 * @param left  the first domain
	 * @param right the second domain
	 * 
	 * @return the new instance of product
	 */
	public abstract C mk(
			T1 left,
			T2 right);

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((left == null) ? 0 : left.hashCode());
		result = prime * result + ((right == null) ? 0 : right.hashCode());
		return result;
	}

	@Override
	public boolean equals(
			Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		NonRelationalValueCartesianProduct other = (NonRelationalValueCartesianProduct) obj;
		if (left == null) {
			if (other.left != null)
				return false;
		} else if (!left.equals(other.left))
			return false;
		if (right == null) {
			if (other.right != null)
				return false;
		} else if (!right.equals(other.right))
			return false;
		return true;
	}

	@Override
	public StructuredRepresentation representation() {
		return new ListRepresentation(left.representation(), right.representation());
	}

	@Override
	public C top() {
		return mk(left.top(), right.top());
	}

	@Override
	public boolean isTop() {
		return left.isTop() && right.isTop();
	}

	@Override
	public C bottom() {
		return mk(left.bottom(), right.bottom());
	}

	@Override
	public boolean isBottom() {
		return left.isBottom() && right.isBottom();
	}

	@Override
	public C lubAux(
			C other)
			throws SemanticException {
		return mk(left.lub(other.left), right.lub(other.right));
	}

	@Override
	public C wideningAux(
			C other)
			throws SemanticException {
		return mk(left.widening(other.left), right.widening(other.right));
	}

	@Override
	public boolean lessOrEqualAux(
			C other)
			throws SemanticException {
		return left.lessOrEqual(other.left) && right.lessOrEqual(other.right);
	}

	@Override
	public C eval(
			ValueExpression expression,
			ValueEnvironment environment,
			ProgramPoint pp,
			SemanticOracle oracle)
			throws SemanticException {
		ValueEnvironment lenv = new ValueEnvironment<>(left);
		ValueEnvironment renv = new ValueEnvironment<>(right);
		for (Entry entry : environment) {
			lenv = lenv.putState(entry.getKey(), entry.getValue().left);
			renv = renv.putState(entry.getKey(), entry.getValue().right);
		}

		return mk(left.eval(expression, lenv, pp, oracle), right.eval(expression, renv, pp, oracle));
	}

	@Override
	public Satisfiability satisfies(
			ValueExpression expression,
			ValueEnvironment environment,
			ProgramPoint pp,
			SemanticOracle oracle)
			throws SemanticException {
		ValueEnvironment lenv = new ValueEnvironment<>(left);
		ValueEnvironment renv = new ValueEnvironment<>(right);
		for (Entry entry : environment) {
			lenv = lenv.putState(entry.getKey(), entry.getValue().left);
			renv = renv.putState(entry.getKey(), entry.getValue().right);
		}

		return left.satisfies(expression, lenv, pp, oracle).glb(right.satisfies(expression, renv, pp, oracle));
	}

	@Override
	public ValueEnvironment assume(
			ValueEnvironment environment,
			ValueExpression expression,
			ProgramPoint src,
			ProgramPoint dest,
			SemanticOracle oracle)
			throws SemanticException {
		ValueEnvironment lenv = new ValueEnvironment<>(left);
		ValueEnvironment renv = new ValueEnvironment<>(right);
		for (Entry entry : environment) {
			lenv = lenv.putState(entry.getKey(), entry.getValue().left);
			renv = renv.putState(entry.getKey(), entry.getValue().right);
		}

		ValueEnvironment lassume = left.assume(lenv, expression, src, dest, oracle);
		ValueEnvironment rassume = right.assume(renv, expression, src, dest, oracle);

		@SuppressWarnings("unchecked")
		ValueEnvironment res = new ValueEnvironment<>((C) this);
		for (Entry entry : lassume)
			res = res.putState(entry.getKey(), mk(entry.getValue(), rassume.getState(entry.getKey())));
		for (Entry entry : rassume)
			if (!res.getKeys().contains(entry.getKey()))
				res = res.putState(entry.getKey(), mk(left.bottom(), entry.getValue()));

		return res;
	}

	@Override
	public C glb(
			C other)
			throws SemanticException {
		return mk(left.glb(other.left), right.glb(other.right));
	}

	@Override
	public C fixedVariable(
			Identifier id,
			ProgramPoint pp,
			SemanticOracle oracle)
			throws SemanticException {
		return mk(left.fixedVariable(id, pp, oracle), right.fixedVariable(id, pp, oracle));
	}

	@Override
	public boolean canProcess(
			SymbolicExpression expression,
			ProgramPoint pp,
			SemanticOracle oracle) {
		return left.canProcess(expression, pp, oracle) || right.canProcess(expression, pp, oracle);
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy