// $Id: IfInstruction.java,v 1.1.1.1 1999/12/05 22:19:51 mpp Exp $

package IR2;

import java.util.*;

public class IfInstruction implements HighInstruction {
  protected RValue condition;
  protected Block block_if_true, block_if_false;
  
  // Else block allowed to be null
  public IfInstruction(RValue c, Block a, Block b) throws SemanticTypeException
  {
    condition = c; block_if_true = a; block_if_false = b;
    if (c != null && (c.get_type() != Typed.BOOLEAN))
      throw new SemanticTypeException("non-boolean expression in conditional "+
				      "of if clause");
  }
  
  /* HighInstruction implementation. */
  public Enumeration subblocks() {
    if (block_if_false != null)
      return new ShortEnumeration(block_if_true, block_if_false);
    else
      return new ShortEnumeration(block_if_true);
  }
  
  public LowInstruction destructure(LowInstruction next) {
    LowInstruction ifinstr = 
      condition.short_circuit(block_if_true.destructure(next),
			      block_if_false != null
			      ? block_if_false.destructure(next)
			      : next);
    next.add_label(); // Will need to jump here
    return ifinstr;
  }
  
  /* Walkable implementation. */
  public String node_name() {
    return "if_instruction";
  }
  
  public Enumeration neighbors() {
    if (block_if_false != null)
      return new ShortEnumeration(condition, block_if_true,
				  block_if_false);
    else
      return new ShortEnumeration(condition, block_if_true);
  }
  
  public String pretty_print(int indent, boolean recursive) {
    String output = new String();
    
    for (int i = 0; i < indent; i++) output += " ";
    if (recursive) {
      indent += 2;
      output += "(" + this.node_name() + "\n";
      /* stuff - calls to prettyprints of internals of this node*/
      for (Enumeration e = this.neighbors(); e.hasMoreElements();) {
	Walkable foo = (Walkable)e.nextElement();
	if (foo == null) 
	  output += "-error-";
	else
	  output += foo.pretty_print(indent, true);
      }
      for (int i = 0; i < indent; i++) output += " ";
      output += ") /* "+ this.node_name() + " */\n";
    } else {
      output += "(" + this.node_name() + ")\n";
    }
    return output;
  }
}
