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

it.unive.lisa.analysis.numeric.UpperBounds Maven / Gradle / Ivy

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

import it.unive.lisa.analysis.Lattice;
import it.unive.lisa.analysis.SemanticException;
import it.unive.lisa.analysis.SemanticOracle;
import it.unive.lisa.analysis.nonrelational.value.BaseNonRelationalValueDomain;
import it.unive.lisa.analysis.nonrelational.value.ValueEnvironment;
import it.unive.lisa.program.cfg.ProgramPoint;
import it.unive.lisa.symbolic.value.Identifier;
import it.unive.lisa.symbolic.value.ValueExpression;
import it.unive.lisa.symbolic.value.operator.binary.BinaryOperator;
import it.unive.lisa.symbolic.value.operator.binary.ComparisonEq;
import it.unive.lisa.symbolic.value.operator.binary.ComparisonGe;
import it.unive.lisa.symbolic.value.operator.binary.ComparisonGt;
import it.unive.lisa.symbolic.value.operator.binary.ComparisonLe;
import it.unive.lisa.symbolic.value.operator.binary.ComparisonLt;
import it.unive.lisa.util.representation.SetRepresentation;
import it.unive.lisa.util.representation.StringRepresentation;
import it.unive.lisa.util.representation.StructuredRepresentation;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Objects;
import java.util.Set;
import java.util.TreeSet;

/**
 * The upper bounds abstract domain. It is implemented as a
 * {@link BaseNonRelationalValueDomain}.
 * 
 * @author Luca Negrini
 * @author Vincenzo Arceri
 */
public class UpperBounds implements BaseNonRelationalValueDomain, Iterable {

	/**
	 * The abstract top element.
	 */
	private static final UpperBounds TOP = new UpperBounds(true);

	/**
	 * The abstract bottom element.
	 */
	private static final UpperBounds BOTTOM = new UpperBounds(new TreeSet<>());

	/**
	 * The flag to set abstract top state.
	 */
	private final boolean isTop;

	/**
	 * The set containing the bounds.
	 */
	private final Set bounds;

	/**
	 * Builds the upper bounds.
	 */
	public UpperBounds() {
		this(true);
	}

	/**
	 * Builds the upper bounds.
	 * 
	 * @param isTop {@code true} if the abstract domain is top; otherwise
	 *                  {@code false}.
	 */
	public UpperBounds(
			boolean isTop) {
		this.bounds = null;
		this.isTop = isTop;
	}

	/**
	 * Builds the upper bounds.
	 * 
	 * @param bounds the bounds to set
	 */
	public UpperBounds(
			Set bounds) {
		this.bounds = bounds;
		this.isTop = false;
	}

	@Override
	public StructuredRepresentation representation() {
		if (isTop())
			return new StringRepresentation("{}");
		if (isBottom())
			return Lattice.bottomRepresentation();
		return new SetRepresentation(bounds, StringRepresentation::new);
	}

	@Override
	public UpperBounds top() {
		return TOP;
	}

	@Override
	public UpperBounds bottom() {
		return BOTTOM;
	}

	@Override
	public boolean isBottom() {
		return !isTop && bounds.isEmpty();
	}

	@Override
	public UpperBounds lubAux(
			UpperBounds other)
			throws SemanticException {
		Set lub = new HashSet<>(bounds);
		lub.retainAll(other.bounds);
		return new UpperBounds(lub);
	}

	@Override
	public UpperBounds glbAux(
			UpperBounds other)
			throws SemanticException {
		Set lub = new HashSet<>(bounds);
		lub.addAll(other.bounds);
		return new UpperBounds(lub);
	}

	@Override
	public boolean lessOrEqualAux(
			UpperBounds other)
			throws SemanticException {
		return bounds.containsAll(other.bounds);
	}

	@Override
	public UpperBounds wideningAux(
			UpperBounds other)
			throws SemanticException {
		return other.bounds.containsAll(bounds) ? other : TOP;
	}

	@Override
	public boolean equals(
			Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		UpperBounds other = (UpperBounds) obj;
		return Objects.equals(bounds, other.bounds) && isTop == other.isTop;
	}

	@Override
	public int hashCode() {
		return Objects.hash(bounds, isTop);
	}

	@Override
	public ValueEnvironment assumeBinaryExpression(
			ValueEnvironment environment,
			BinaryOperator operator,
			ValueExpression left,
			ValueExpression right,
			ProgramPoint src,
			ProgramPoint dest,
			SemanticOracle oracle)
			throws SemanticException {
		if (!(left instanceof Identifier && right instanceof Identifier))
			return environment;

		Identifier x = (Identifier) left;
		Identifier y = (Identifier) right;

		// glb is the union!

		if (operator instanceof ComparisonEq) {
			// x == y
			UpperBounds set = environment.getState(x).glb(environment.getState(y));
			return environment.putState(x, set).putState(y, set);
		}

		if (operator instanceof ComparisonLt) {
			// x < y
			UpperBounds set = environment.getState(x).glb(environment.getState(y))
					.glb(new UpperBounds(Collections.singleton(y)));
			return environment.putState(x, set);
		}

		if (operator instanceof ComparisonLe) {
			// x <= y
			UpperBounds set = environment.getState(x).glb(environment.getState(y));
			return environment.putState(x, set);
		}

		if (operator instanceof ComparisonGt) {
			// x > y ---> y < x
			UpperBounds set = environment.getState(x).glb(environment.getState(y))
					.glb(new UpperBounds(Collections.singleton(x)));
			return environment.putState(y, set);
		}

		if (operator instanceof ComparisonGe) {
			// x >= y --- > y <= x
			UpperBounds set = environment.getState(x).glb(environment.getState(y));
			return environment.putState(y, set);
		}

		return environment;
	}

	@Override
	public Iterator iterator() {
		if (bounds == null)
			return Collections.emptyIterator();
		return bounds.iterator();
	}

	/**
	 * Checks if this bounds contains a specified identifier of a program
	 * variable.
	 * 
	 * @param id the identifier to check
	 * 
	 * @return {@code true} if this bounds contains the specified identifier;
	 *             otherwise, {@code false}.
	 */
	public boolean contains(
			Identifier id) {
		return bounds != null && bounds.contains(id);
	}

	/**
	 * Adds the specified identifier of a program variable in the bounds.
	 * 
	 * @param id the identifier to add in the bounds.
	 * 
	 * @return the updated bounds.
	 */
	public UpperBounds add(
			Identifier id) {
		Set res = new HashSet<>();
		if (!isTop() && !isBottom())
			res.addAll(bounds);
		res.add(id);
		return new UpperBounds(res);
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy