package accrue.analysis.ext;

import polyglot.ast.Ext;
import polyglot.visit.FlowGraph.PeerKey;
import accrue.analysis.interprocanalysis.AnalysisContext;
import accrue.analysis.pointer.RegisterPointerStmtsVisitor;
import accrue.analysis.pointer.StmtRegistrar;

public interface AccrueExt extends Ext {

    void registerPointerStmts(StmtRegistrar registrar,
            RegisterPointerStmtsVisitor v);

    <T> void recordAnalysisResult(Object analysisKey, T result);

    <T> void recordAnalysisResult(Object analysisKey, AnalysisContext context,
            PeerKey peerKey, T result);

    <T> void recordAnalysisResult(Object analysisKey, AnalysisContext context,
            T result);

    <T> T removeAnalysisResult(Object analysisKey);

    <T> T removeAnalysisResult(Object analysisKey, AnalysisContext context,
            PeerKey peerKey);

    <T> T removeAnalysisResult(Object analysisKey, AnalysisContext context);

    <T> T getAnalysisResult(Object analysisKey, AnalysisContext context,
            PeerKey peerKey);

    <T> T getAnalysisResult(Object analysisKey, AnalysisContext context);

    <T> T getAnalysisResult(Object analysisKey);

    /**
     * During a dataflow analysis, when this term is encountered, how many 
     * arguments should there be on the expression result stack? For example,
     * for an addition (e1 + e2) there will be two, one for each operand. For 
     * a field access (o.f) there will be one, the target of the access. In general,
     * this will return a meaningful number only for expressions.
     * 
     * @see accrue.analysis.interprocvarcontext.VarContextDataFlow
     * @return
     */
    int numArgumentsOnResultStack();

    /**
     * How many enclosing finally blocks is this node nested inside? This information
     * is used during dataflow analysis to help manage syspended execution contexts.
     * 
     * Example depths are given here.
     * <pre>
     * void m() {
     *   ; // finally depth here is 0
     *   try {
     *     ; // finally depth here is 0
     *   }
     *   finally {
     *     ; // finally depth here is 1
     *     try {
     *       ; // finally depth here is 1
     *     }
     *     catch (Exception e) {
     *       ; // finally depth here is 1
     *       ... 
     *     }
     *     finally {
     *       ; // finally depth here is 2
     *     }
     *     ; // finally depth here is 1
     *   }
     *   ; // finally depth here is 0
     * }
     * </pre>
     * Note that for a finally block node, the number of enclosing finally blocks
     * does not include itself.
     * @return Number of enclosing finally blocks, null if not yet computed.
     */
    Integer enclosingFinallyDepth();

    /**
     * Set the number of finally blocks that this node is nested inside.
     * @param finallyDepth
     */
    void setEnclosingFinallyDepth(int finallyDepth);

}
