package accrue.analysis.pointer;

import polyglot.types.CodeInstance;
import polyglot.types.Type;
import polyglot.util.InternalCompilerError;
import polyglot.util.Position;
import accrue.analysis.pointer.PointsToEngine.StmtAndContext;
import accrue.analysis.pointer.analyses.HeapAbstractionFactory;

public abstract class PointsToStmt {
    public final Position origin;

    /**
     * The codeInstance (methods, constructors, static initializers, and static field decls) in which this statement occurs.
     * Note that for statements that were in instance initializers, there will
     * be multiple statements, one for each constructor that they occur in
     */
    final CodeInstance codeInstance;

    public PointsToStmt(Position origin, CodeInstance code, Type leftType,
            Type rightType, boolean isRightTypePrecise) {
        this.origin = origin;
        this.codeInstance = code;
        checkTypes(leftType, rightType, isRightTypePrecise);
    }

    private void checkTypes(Type leftType, Type rightType,
            boolean isRightTypePrecise) {
        if (leftType == null && rightType == null) return;
        if (rightType.isSubtype(leftType)
                || rightType.isImplicitCastValid(leftType)) {
            return;
        }
        if (!isRightTypePrecise) {
            // the right type isn't precise, so there may actually be
            // a subtype of the rhs..
            if (leftType.isSubtype(rightType)
                    || leftType.isCastValid(rightType)) {
                return;
            }
        }
        throw new InternalCompilerError("Assignment " + this
                                                + " seems screwy, from "
                                                + rightType + " to " + leftType,
                                        origin);
    }

    /**
     * Add appropriate edges to the graph g given the context for the LocalNodes and
     * ThisNode. Return true if and only if changes were made to the graph
     */
    public abstract boolean process(CContext context, PointsToGraph g,
            StmtRegistrar registrar, HeapAbstractionFactory af,
            StmtAndContext sac);

    @Override
    public abstract String toString();

    @Override
    public final boolean equals(Object o) {
        return super.equals(o);
    }

    @Override
    public final int hashCode() {
        return super.hashCode();
    }
}
