/**
 * 
 */
package accrue.analysis.pointer;

import polyglot.main.Report;
import polyglot.types.CodeInstance;
import polyglot.types.ReferenceType;
import polyglot.util.Position;
import accrue.analysis.AnalysisTopics;
import accrue.analysis.pointer.PointsToEngine.StmtAndContext;
import accrue.analysis.pointer.analyses.HeapAbstractionFactory;

public class StmtAllocToLocal extends PointsToStmt {
    protected final ReferenceVariable left;
    protected final AllocSiteNode right;

    public StmtAllocToLocal(ReferenceVariable left, AllocSiteNode right,
            Position origin, CodeInstance code) {
        super(origin,
              code,
              left.expectedType(),
              right.expectedType(),
              right.isPreciseType());
        this.left = left;
        this.right = right;

        if (right.expectedType() != null && right.expectedType().isReference()) {
            // force the type system to load the methods and fields of the classes,
            // to make sure we don't get any surprises (i.e., last minute class loading) 
            // while solving the points-to constraints.
            ReferenceType rt = right.expectedType().toReference();
            while (rt != null) {
                rt.methods();
                rt.fields();
                rt =
                        (rt.superType() == null) ? null : rt.superType()
                                                            .toReference();
            }
        }
    }

    @Override
    public String toString() {
        return left + " := new " + right;
    }

    @Override
    public boolean process(CContext context, PointsToGraph g,
            StmtRegistrar registrar, HeapAbstractionFactory af,
            StmtAndContext sac) {
        if (Report.should_report(AnalysisTopics.POINTSTO, 3))
            Report.report(3, "Processing alloc to local " + this
                    + " in context " + context);
        return g.addEdge(sac,
                         ReferenceVariableReplica.create(context, left, af),
                         af.record(context, right),
                         origin);
    }

}
