it.unive.lisa.analysis.traces.ExecutionTrace 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.traces;
import it.unive.lisa.program.cfg.ProgramPoint;
import java.util.Arrays;
import org.apache.commons.lang3.StringUtils;
/**
* An execution trace, made of {@link TraceToken}s representing the
* intraprocedural control-flow instructions that have been traversed up to now.
*
* @author Luca Negrini
*/
public class ExecutionTrace {
private static final TraceToken[] EMPTY_TRACE = new TraceToken[0];
private final TraceToken[] tokens;
/**
* Builds a new empty execution trace.
*/
public ExecutionTrace() {
tokens = EMPTY_TRACE;
}
private ExecutionTrace(
TraceToken[] tokens) {
this.tokens = tokens;
}
/**
* Adds the given {@link TraceToken} at the top of this trace.
*
* @param token the token to add
*
* @return the updated trace
*/
public ExecutionTrace push(
TraceToken token) {
int len = this.tokens.length;
TraceToken[] tokens = new TraceToken[len + 1];
System.arraycopy(this.tokens, 0, tokens, 0, len);
tokens[len] = token;
return new ExecutionTrace(tokens);
}
/**
* Removes the head of this trace.
*
* @return the updated trace
*/
public ExecutionTrace pop() {
if (tokens.length == 0)
return this;
int len = this.tokens.length;
TraceToken[] tokens = new TraceToken[len - 1];
System.arraycopy(this.tokens, 0, tokens, 0, len - 1);
return new ExecutionTrace(tokens);
}
/**
* Yields the head of the execution trace.
*
* @return the head
*/
public TraceToken getHead() {
return tokens[tokens.length - 1];
}
/**
* Yields the number of {@link Branching} tokens in this trace.
*
* @return the number of branches
*/
public int numberOfBranches() {
int count = 0;
for (TraceToken token : tokens)
if (token instanceof Branching)
count++;
return count;
}
/**
* Yields the last loop token ({@link LoopSummary} or {@link LoopIteration})
* for the given guard, if any.
*
* @param guard the loop guard
*
* @return the last (top-most) loop token for the given guard, or
* {@code null} if no such token exist
*/
public TraceToken lastLoopTokenFor(
ProgramPoint guard) {
for (int i = tokens.length - 1; i >= 0; i--) {
TraceToken tok = tokens[i];
if ((tok instanceof LoopSummary || tok instanceof LoopIteration) && tok.getProgramPoint() == guard)
return tok;
}
return null;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + Arrays.hashCode(tokens);
return result;
}
@Override
public boolean equals(
Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
ExecutionTrace other = (ExecutionTrace) obj;
if (!Arrays.equals(tokens, other.tokens))
return false;
return true;
}
@Override
public String toString() {
return "<" + StringUtils.join(tokens, "::") + ">";
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy