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

dataflow.src.org.checkerframework.dataflow.analysis.AnalysisResult Maven / Gradle / Ivy

package org.checkerframework.dataflow.analysis;

/*>>>
import org.checkerframework.checker.nullness.qual.Nullable;
*/

import org.checkerframework.dataflow.cfg.block.Block;
import org.checkerframework.dataflow.cfg.block.ExceptionBlock;
import org.checkerframework.dataflow.cfg.block.RegularBlock;
import org.checkerframework.dataflow.cfg.node.Node;

import java.util.HashMap;
import java.util.IdentityHashMap;
import java.util.Map;
import java.util.Map.Entry;

import javax.lang.model.element.Element;

import com.sun.source.tree.Tree;

/**
 * An {@link AnalysisResult} represents the result of a org.checkerframework.dataflow analysis by
 * providing the abstract values given a node or a tree. Note that it does not
 * keep track of custom results computed by some analysis.
 *
 * @author Stefan Heule
 *
 * @param 
 *            type of the abstract value that is tracked.
 */
public class AnalysisResult, S extends Store> {

    /** Abstract values of nodes. */
    protected final IdentityHashMap nodeValues;

    /** Map from AST {@link Tree}s to {@link Node}s. */
    protected final IdentityHashMap treeLookup;

    /** Map from (effectively final) local variable elements to their abstract value. */
    protected final HashMap finalLocalValues;

    /**
     * The stores before every method call.
     */
    protected final IdentityHashMap> stores;

    /**
     * Initialize with a given node-value mapping.
     */
    public AnalysisResult(Map nodeValues,
            IdentityHashMap> stores,
            IdentityHashMap treeLookup, HashMap finalLocalValues) {
        this.nodeValues = new IdentityHashMap<>(nodeValues);
        this.treeLookup = new IdentityHashMap<>(treeLookup);
        this.stores = stores;
        this.finalLocalValues = finalLocalValues;
    }

    /**
     * Initialize empty result.
     */
    public AnalysisResult() {
        nodeValues = new IdentityHashMap<>();
        treeLookup = new IdentityHashMap<>();
        stores = new IdentityHashMap<>();
        finalLocalValues = new HashMap<>();
    }

    /**
     * Combine with another analysis result.
     */
    public void combine(AnalysisResult other) {
        for (Entry e : other.nodeValues.entrySet()) {
            nodeValues.put(e.getKey(), e.getValue());
        }
        for (Entry e : other.treeLookup.entrySet()) {
            treeLookup.put(e.getKey(), e.getValue());
        }
        for (Entry> e : other.stores.entrySet()) {
            stores.put(e.getKey(), e.getValue());
        }
        for (Entry e : other.finalLocalValues.entrySet()) {
            finalLocalValues.put(e.getKey(), e.getValue());
        }
    }

    /**
     * @return The value of effectively final local variables.
     */
    public HashMap getFinalLocalValues() {
        return finalLocalValues;
    }

    /**
     * @return The abstract value for {@link Node} {@code n}, or {@code null} if
     *         no information is available.
     */
    public /*@Nullable*/ A getValue(Node n) {
        return nodeValues.get(n);
    }

    /**
     * @return The abstract value for {@link Tree} {@code t}, or {@code null} if
     *         no information is available.
     */
    public /*@Nullable*/ A getValue(Tree t) {
        A val = getValue(treeLookup.get(t));
        return val;
    }

    /**
     * @return The {@link Node} for a given {@link Tree}.
     */
    public /*@Nullable*/ Node getNodeForTree(Tree tree) {
        return treeLookup.get(tree);
    }

    /**
     * @return The store immediately before a given {@link Tree}.
     */
    public S getStoreBefore(Tree tree) {
        Node node = getNodeForTree(tree);
        if (node == null) {
            return null;
        }
        return getStoreBefore(node);
    }

    /**
     * @return The store immediately before a given {@link Node}.
     */
    public S getStoreBefore(Node node) {
        return runAnalysisFor(node, true);
    }

    /**
     * @return The store immediately after a given {@link Tree}.
     */
    public S getStoreAfter(Tree tree) {
        Node node = getNodeForTree(tree);
        if (node == null) {
            return null;
        }
        return runAnalysisFor(node, false);
    }

    /**
     * Runs the analysis again within the block of {@code node} and returns the
     * store at the location of {@code node}. If {@code before} is true, then
     * the store immediately before the {@link Node} {@code node} is returned.
     * Otherwise, the store after {@code node} is returned.
     *
     * 

* If the given {@link Node} cannot be reached (in the control flow graph), * then {@code null} is returned. */ protected S runAnalysisFor(Node node, boolean before) { Block block = node.getBlock(); TransferInput transferInput = stores.get(block); if (transferInput == null) { return null; } return runAnalysisFor(node, before, transferInput); } /** * Runs the analysis again within the block of {@code node} and returns the * store at the location of {@code node}. If {@code before} is true, then * the store immediately before the {@link Node} {@code node} is returned. * Otherwise, the store after {@code node} is returned. */ public static , S extends Store> S runAnalysisFor( Node node, boolean before, TransferInput transferInput) { assert node != null; Block block = node.getBlock(); assert transferInput != null; Analysis analysis = transferInput.analysis; Node oldCurrentNode = analysis.currentNode; if (analysis.isRunning) { return analysis.currentInput.getRegularStore(); } analysis.isRunning = true; try { switch (block.getType()) { case REGULAR_BLOCK: { RegularBlock rb = (RegularBlock) block; // Apply transfer function to contents until we found the node // we // are looking for. TransferInput store = transferInput; TransferResult transferResult = null; for (Node n : rb.getContents()) { analysis.currentNode = n; if (n == node && before) { return store.getRegularStore(); } transferResult = analysis.callTransferFunction(n, store); if (n == node) { return transferResult.getRegularStore(); } store = new TransferInput<>(n, analysis, transferResult); } // This point should never be reached. If the block of 'node' is // 'block', then 'node' must be part of the contents of 'block'. assert false; return null; } case EXCEPTION_BLOCK: { ExceptionBlock eb = (ExceptionBlock) block; // apply transfer function to content assert eb.getNode() == node; if (before) { return transferInput.getRegularStore(); } analysis.currentNode = node; TransferResult transferResult = analysis .callTransferFunction(node, transferInput); return transferResult.getRegularStore(); } default: // Only regular blocks and exceptional blocks can hold nodes. assert false; break; } return null; } finally { analysis.currentNode = oldCurrentNode; analysis.isRunning = false; } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy