package IR2;

import java.util.*;

public class BasicBlock implements Traversable {
  private DelocalizedInstruction first;
  private DelocalizedInstruction last;
  private Vector predecessors = new Vector();
  private Vector successors = new Vector();


  // Accessors to manipulate the DelocalizedInstructions in a block
  public DelocalizedInstruction next_instr(DelocalizedInstruction di) {
    if (di == last) return null; else return di.next_instr();
  }
  public DelocalizedInstruction prev_instr(DelocalizedInstruction di) {
    if (di == first) return null; else return di.prev_instr();
  }
  // Removes given instruction; returns the first next instruction in block
  // Assume not removing an instruction with multiple nexts. (cbr)
  // Assume i's next doesn't have multiple prev's. (couldn't be in same block)
  // However, i *could* have multiple prev's (if i is start of block)
  // Block *could* become empty.
  public DelocalizedInstruction removeElement(DelocalizedInstruction i){
    DelocalizedInstruction next = i.next_instr();
    DelocalizedInstruction next_in_block = this.next_instr(i);

    // Propagate labels if needed 
    if (next != null) // shouldn't be!
      for (Enumeration e = i.get_labels(); e.hasMoreElements(); ) {
        String label = (String)e.nextElement();
        next.add_label(label);
      }
    
    // All prev's now have i's next for a next.
    if (first == i) { // Weirdness could ensue. Be general.
	DelocalizedInstruction di;
	if (next != null) next.clear_prev();
	if (last == i) { first = last = null; } else first = next;
	
	for (Enumeration e = i.prev(); e.hasMoreElements(); ) {
	  di = (DelocalizedInstruction)e.nextElement();
	  di.replace_next(i, next);
	  if (next != null) next.add_prev_instr(di);
	}
    } else { // Only one prev, guaranteed.
      DelocalizedInstruction prev = i.prev_instr();
      if (next != null) 
	next.set_prev_instr(prev);
      if (prev != null)
	prev.set_next_instr(next);
      
      if (i == last) last = prev;
    }

    return next_in_block;
  }

  


  public void add_predecessor(BasicBlock blk) {
    predecessors.addElement(blk);
  }
  public void add_successor(BasicBlock blk) {
    successors.addElement(blk);
  }
  public void remove_predecessor(BasicBlock blk) {
    predecessors.removeElement(blk); 
  }
  public void remove_successor(BasicBlock blk) {
    successors.removeElement(blk); 
  }

  public void add_instruction(DelocalizedInstruction di) {
    if (first == null) first = di;
    last = di;
  }

  public DelocalizedInstruction get_first() {
    return first;
  }
  public DelocalizedInstruction get_last() {
    return last;
  }


  public Enumeration get_predecessors() {
    return predecessors.elements();
  }
  public Enumeration get_successors() {
    return successors.elements();
  }

  // This enumeration will include this and all reachable successors (once!)
  public Enumeration self_and_all_successors() {
    return (new FlatteningTraversal()).flatten(this);
  }

  /* implements Traversable */
  public void traverse(Traversal t) {
    Enumeration e = get_successors();
    while (e.hasMoreElements())
      t.traverse((Traversable) e.nextElement());
  }

}
