package accrue.analysis.pointer;

import polyglot.types.Type;
import polyglot.util.InternalCompilerError;
import polyglot.util.Position;

/**
 * A ReferenceVariable represents the result of an expression.
 * A ReferenceVariableReplica is a ReferenceVariable with a CContext.
 */
public class ReferenceVariable {
    /**
     * Unique identifier
     */
    private final int id;
    private final String debugString;
    private final Position pos;

    public static final boolean SHOW_POSITION = true;

    private static int generator;

    /**
     * This field is set if there is only one such LocalNode 
     * in the whole program. For example, this is true for
     * LocalNodes that represent static fields.
     */
    private final boolean isSingleton;
    private final Type expectedType;

    public ReferenceVariable(String debugString, boolean isSingleton,
            Type expectedType, Position pos) {
        this.id = ++generator;
        this.debugString = debugString;
        this.pos = pos;
        if (debugString == null) {
            throw new InternalCompilerError("Need debug string");
        }
        if ("null".equals(debugString)) {
            throw new InternalCompilerError("Whacky debug string");
        }
        this.isSingleton = isSingleton;
        this.expectedType = expectedType;
    }

    /**
     * Is this graph base node a singleton? That is, should there
     * be only a single ReferenceVariableReplica for it? This should
     * return true for reference variables that represent e.g., static
     * fields. Because there is only one location represented by 
     * the static field, there should not be multiple replicas of the
     * reference variable that represents the static field.
     */
    public boolean isSingletonReferenceVariable() {
        return this.isSingleton;
    }

    public Type expectedType() {
        return expectedType;
    }

    @Override
    public String toString() {
        if (SHOW_POSITION) {
            return debugString + "{" + id + ":" + pos.file() + ":" + pos.line()
                    + "}";
        }
        return debugString + "{" + id + "}";
    }

    @Override
    final public boolean equals(Object o) {
        return this == o;
    }

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

}
