it.unive.lisa.analysis.combination.CartesianProduct Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of lisa-analyses Show documentation
Show all versions of lisa-analyses Show documentation
A library for static analysis
The newest version!
package it.unive.lisa.analysis.combination;
import it.unive.lisa.analysis.Lattice;
import it.unive.lisa.analysis.ScopeToken;
import it.unive.lisa.analysis.SemanticDomain;
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.Environment;
import it.unive.lisa.program.cfg.ProgramPoint;
import it.unive.lisa.symbolic.SymbolicExpression;
import it.unive.lisa.symbolic.value.Identifier;
import it.unive.lisa.util.representation.ListRepresentation;
import it.unive.lisa.util.representation.StructuredRepresentation;
import java.util.Collection;
import java.util.function.Predicate;
/**
* A generic Cartesian product abstract domain between two non-communicating
* {@link SemanticDomain}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 Vincenzo Arceri
*
* @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
* @param the type of {@link SymbolicExpression} that {@code } and
* {@code }, and in turn this domain, can process
* @param the type of {@link Identifier} that {@code } and
* {@code }, and in turn this domain, handle
*/
public abstract class CartesianProduct,
T1 extends SemanticDomain & Lattice,
T2 extends SemanticDomain & Lattice,
E extends SymbolicExpression,
I extends Identifier> implements SemanticDomain, Lattice {
/**
* 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 CartesianProduct(
T1 left,
T2 right) {
this.left = left;
this.right = 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;
CartesianProduct, ?, ?, ?, ?> other = (CartesianProduct, ?, ?, ?, ?>) 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 String toString() {
if (left instanceof Environment && right instanceof Environment) {
Environment, ?, ?> leftEnv = (Environment, ?, ?>) left;
Environment, ?, ?> rightEnv = (Environment, ?, ?>) right;
if (!leftEnv.isTop() && !leftEnv.isBottom()) {
StringBuilder result = new StringBuilder();
for (Identifier x : leftEnv.getKeys())
result.append(x)
.append(": (")
.append(leftEnv.getState(x).representation())
.append(", ")
.append(rightEnv.getState(x).representation())
.append(")\n");
return result.toString();
} else if (!rightEnv.isTop() && !rightEnv.isBottom()) {
StringBuilder result = new StringBuilder();
for (Identifier x : rightEnv.getKeys())
result.append(x)
.append(": (")
.append(leftEnv.getState(x).representation())
.append(", ")
.append(rightEnv.getState(x).representation())
.append(")\n");
return result.toString();
}
}
return "(" + left.representation() + ", " + right.representation() + ")";
}
/**
* 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 StructuredRepresentation representation() {
return new ListRepresentation(left.representation(), right.representation());
}
@Override
public C assign(
I id,
E expression,
ProgramPoint pp,
SemanticOracle oracle)
throws SemanticException {
T1 newLeft = left.assign(id, expression, pp, oracle);
T2 newRight = right.assign(id, expression, pp, oracle);
return mk(newLeft, newRight);
}
@Override
public C smallStepSemantics(
E expression,
ProgramPoint pp,
SemanticOracle oracle)
throws SemanticException {
T1 newLeft = left.smallStepSemantics(expression, pp, oracle);
T2 newRight = right.smallStepSemantics(expression, pp, oracle);
return mk(newLeft, newRight);
}
@Override
public C assume(
E expression,
ProgramPoint src,
ProgramPoint dest,
SemanticOracle oracle)
throws SemanticException {
T1 newLeft = left.assume(expression, src, dest, oracle);
T2 newRight = right.assume(expression, src, dest, oracle);
return mk(newLeft, newRight);
}
@Override
public C forgetIdentifier(
Identifier id)
throws SemanticException {
T1 newLeft = left.forgetIdentifier(id);
T2 newRight = right.forgetIdentifier(id);
return mk(newLeft, newRight);
}
@Override
public C forgetIdentifiersIf(
Predicate test)
throws SemanticException {
T1 newLeft = left.forgetIdentifiersIf(test);
T2 newRight = right.forgetIdentifiersIf(test);
return mk(newLeft, newRight);
}
@Override
public C pushScope(
ScopeToken scope)
throws SemanticException {
T1 newLeft = left.pushScope(scope);
T2 newRight = right.pushScope(scope);
return mk(newLeft, newRight);
}
@Override
public C popScope(
ScopeToken scope)
throws SemanticException {
T1 newLeft = left.popScope(scope);
T2 newRight = right.popScope(scope);
return mk(newLeft, newRight);
}
@Override
public Satisfiability satisfies(
E expression,
ProgramPoint pp,
SemanticOracle oracle)
throws SemanticException {
return left.satisfies(expression, pp, oracle).and(right.satisfies(expression, pp, oracle));
}
@Override
public C lub(
C other)
throws SemanticException {
return mk(left.lub(other.left), right.lub(other.right));
}
@Override
public C widening(
C other)
throws SemanticException {
return mk(left.widening(other.left), right.widening(other.right));
}
@Override
public boolean lessOrEqual(
C other)
throws SemanticException {
return left.lessOrEqual(other.left) && right.lessOrEqual(other.right);
}
@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 > Collection getAllDomainInstances(
Class domain) {
Collection result = SemanticDomain.super.getAllDomainInstances(domain);
result.addAll(left.getAllDomainInstances(domain));
result.addAll(right.getAllDomainInstances(domain));
return result;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy