package accrue.analysis.defuse;

import polyglot.ast.ProcedureDecl;
import polyglot.types.SemanticException;
import accrue.AccrueExtensionInfo;
import accrue.analysis.AnalysisTopics;
import accrue.analysis.defuse.DefUseAnalysisUtil.Mode;
import accrue.analysis.interprocanalysis.AnalysisUnit;
import accrue.analysis.interprocanalysis.AnalysisUtil;
import accrue.analysis.interprocanalysis.WorkQueue;
import accrue.analysis.interprocvarcontext.AnalysisFactoryVarContext;
import accrue.analysis.interprocvarcontext.VarContext;

public class DefUseAnalysisFactory extends
        AnalysisFactoryVarContext<DefUseAbsVal> {
    public static final String ANALYSIS_NAME = "accrue.analysis.defuse";

    public static final String OBSERVED_LOCATIONS = ANALYSIS_NAME + ".OBSERVED";
    /**
     * Stores the set of output dependencies  
     */
    public static final String INTRA_OUTPUT_DEPENDENCIES = ANALYSIS_NAME
            + ".INTRA_OUTPUT";

    /**
     * This analysis result stores a Set<EdgeIdentifier> pointing to definitions of locations used.
     */
    public static final String DATA_DEPENDENCIES = ANALYSIS_NAME + ".USES";

    /**
     * This analysis result stores a Set<EdgeIdentifier> pointing to definitions of locations used.
     * Inter-procedural dependencies are summarized at call sites.
     */
    public static final String INTRA_DATA_DEPENDENCIES = ANALYSIS_NAME
            + ".INTRA_USES";

    /**
     * This analysis result stores a Set<AbstractLocation> of modified heap locations.
     */
    public static final String MODIFIED_LOCATIONS = ANALYSIS_NAME + ".DEFS";

    private final Mode mode;
    private final boolean trackStrings;

    public DefUseAnalysisFactory(AccrueExtensionInfo extInfo,
            DefUseAnalysisUtil.Mode mode, boolean trackStrings) {
        super(extInfo);
        this.mode = mode;
        this.trackStrings = trackStrings;
    }

    @Override
    public String analysisName() {
        return ANALYSIS_NAME;
    }

    @Override
    public String analysisReportName() {
        return AnalysisTopics.DEFUSE;
    }

    @Override
    public DefUseAbsVal bottomAbstractValue() {
        return DefUseAbsVal.EMPTY;
    }

    @Override
    public AnalysisUtil<VarContext<DefUseAbsVal>> analysisUtil(
            WorkQueue<VarContext<DefUseAbsVal>> wq, AnalysisUnit aunit) {
        return new DefUseAnalysisUtil(wq, aunit, extInfo, mode, trackStrings);
    }

    @Override
    public VarContext<DefUseAbsVal> startItem(
            AnalysisUtil<VarContext<DefUseAbsVal>> autil,
            ProcedureDecl startProc) throws SemanticException {
        return new VarContext<DefUseAbsVal>(analysisName(),
                                            bottomAbstractValue());
    }
}
