package IR2;

import java.util.*;

public class DUChain extends Set {
  
  private DelocalizedInstruction start = null, defn, last;
  private DelocalizedLValue lval;
  private Vector uses;
  private boolean debug=false;

  public DUChain(DelocalizedInstruction start) {
    super();
    defn = start;
    lval = start.destination().lproxy();
    uses = new Vector();
  }
  
  // Overrides superclass' method
  public void add(Object o) { addElement(o); } // Not needed, but clearer.
  public void addElement(Object o) {
    // Any uses? Add them to our vector if so.
    Enumeration lvals = ((DelocalizedInstruction)o).lsources();
    while (lvals.hasMoreElements()) {
      if (lvals.nextElement() == lval) {
        uses.addElement(o);
        break;
      }
    }
    if (start == null) start = (DelocalizedInstruction)o;
    last = (DelocalizedInstruction)o;
    super.addElement(o);  // Do the Set Thang.
  }

  /* Overlap detected when one DUChain's start is contained in the other's
     Set */
  public boolean overlap(DUChain foo) {
    return (this.contains(foo.start)||foo.contains(start));
  }

  public DelocalizedLValue get_def() {
    return lval;
  }

  public void substitute_lvalue(DelocalizedLValue newlval) {
    if (lval == newlval) {
      //      System.out.println("uh, repeat assignment ignored");
      return;
    }
    if (debug) System.out.println("DU: Subst: " + defn + " ---> " + newlval);
    // Substitute into the dest of the original definition.
    defn.substitute_lvalue(lval, newlval);
    
    // Perform the substitution on both sides of every instruction, except
    /// other definitions of same lvalue.
    for (Enumeration e = elements(); e.hasMoreElements(); ) {
      DelocalizedInstruction di = (DelocalizedInstruction)e.nextElement();
      di.substitute_rvalue(lval, newlval);
      if (di.destination() == null || di.destination().lproxy() != lval) 
        di.substitute_lvalue(lval, newlval);
    }

    // Set the new lval
    lval = newlval;
  }

  public Enumeration get_uses(){
    return uses.elements();
  }


  // returns true if this chain has a common use (and same Lvalue) with this.
  public boolean related(DUChain foo) {
    // Worth even thinking about this? Are they a def for same var?
    if (this.get_def() != foo.get_def()) return false;

    // Okay, look for common uses of this variable
    Enumeration foo_uses = foo.get_uses();
    while (foo_uses.hasMoreElements()){
      DelocalizedInstruction bar = 
        (DelocalizedInstruction)foo_uses.nextElement();
      if (uses.contains(bar))
        return true;
    }
    return false;
  }
  
  public String toString() { 
    return ">>>" + lval + "<<< [" + defn + "]\n   " + super.toString();
  }

}
