package IRT;

/**
 * An implementation of frames for the ``straight-line IRT code''
 * that we decided to work with on our project.
 * <p>
 * Developed to support student projects in Grinnell College's
 * CSC362 98F.  Make sure to examine the modified Frame.Frame
 * description for more information on structure.
 * <p>
 * A frame has
 * <pre>
 *   FP -> [ Return Address ]
 *         [ Pointer to previous frame (NOT the static link) ]
 *         [ Parameter 0 ]
 *         ...
 *   SP -> 
 * </pre>
 * </p>
 * <strong>History</strong>
 * <dl>
 * <dt>Version 0.2 (16 December 1998)
 * <dd>First distributed version (I think)
 * <dd>Still doesn't have procEntryExit{1,2,3}
 * </dl>
 *
 * @author Samuel A. Rebelsky
 * @version 0.2 of 16 December 1998
 */
public class IRTFrame extends Frame.Frame {
  // +--------+--------------------------------------------------
  // | Fields |
  // +--------+

  /**
   * How many words have been allocated in the current frame?
   */
  int allocated;

  /*
   * public AccessList formals is given in the abstract class
   */
 
  /*
   * public Temp.Label name is given in the abstract class
   */


  // +--------------+--------------------------------------------
  // | Constructors |
  // +--------------+

  /**
   * Build a new frame, filling in the appropriate values.
   */
  public IRTFrame(Temp.Label name, Util.BoolList formals) {
    this.name = name;
    this.allocated = 2;
    this.formals = makeFormals(formals);
  } // IRTFrame(Temp.Label, Util.BoolList)

  /**
   * Build a new frame with no default values.
   */
  public IRTFrame() {
  } // IRTFrame()


  // +---------------+-------------------------------------------
  // | Local Methods |
  // +---------------+

  /**
   * Build a list of formals to the current frame. 
   */
  protected Frame.AccessList makeFormals(Util.BoolList formals) {
    if (formals == null) return null;
    return new Frame.AccessList(allocLocal(formals.head),
                                makeFormals(formals.tail));
  } // makeFormals(Util.BoolList)


  // +---------+-------------------------------------------------
  // | Methods |
  // +---------+

  /**
   * Build a new frame, given information about the parameters to
   * the function.  The booleans indicate whether or not the parameters
   * ``escape'' (if a boolean is true, the corresponding parameter
   * <em>must</em> be stored in the frame).
   * <p>
   * Red book, p. 141.
   */
  public Frame.Frame newFrame(Temp.Label name, Util.BoolList formals) {
    return new IRTFrame(name, formals);
  } // newFrame(Temp.Label, Util.BoolList)

  /**
   * Allocate a new local storage location, which might be a register
   * (temporary) or space in the current frame, or perhaps something
   * different (in some architectures).  As you allocate a new storage
   * location, indicate whether it must be stored in the frame or 
   * whether it can be stored wherever the compiler deems appropriate.
   * <p>
   * Red book, p. 143.
   */
  public Frame.Access allocLocal(boolean escapes) {
    if (escapes) {
      return new InFrame(++this.allocated);
    }
    else {
      return new InReg();
    }
  } // allocLocal(boolean)


  /**
   * Get the register used for the frame pointer.
   * <p>
   * Red book, p. 163.
   */
  public Temp.Temp FP() {
    return new Temp.Temp("FP");
  } // FP()

  /**
   * Get the size of the words on the current machine (in bytes).
   * <p>
   * Red book, p. 163.
   */
  public int wordSize() {
    return 1;
  } /* wordSize() */

  /**
   * Generate the code to call an external function (one of the built-in 
   * functions).
   * <p>
   * Red book, p. 163.
   */
  public Tree.Exp externalCall(String func, Tree.ExpList args) {
    return new Tree.BUILTIN(new Tree.NAME(new Temp.Label(func)),
                            args);
  } // externalCall(String, Tree.ExpList)

  /**
   * A list of all the register names on the machine, which can be used
   * as ``colors'' for register allocation.  Not really needed except for
   * register allocation.
   * <p>
   * Red book, p. 270.
   */
  public Temp.TempList registers() {
    return null;
  } // registers()

  /**
   * Get the register used for the return value.
   * <p>
   * Red book, p. 176.
   */
  public Temp.Temp RV() {
    return new Temp.Temp("RV");
  } // RV()

  /**
   * Get the ``precolored temporary'' that stands for each register.
   * Used primarily for register allocation.
   * <p>
   * Red book, p. 270.
   */
  public String tempMap(Temp.Temp temp) {
    return null;
  } // tempMap(Temp.Temp)

  /**
   * Create the IRT for the start and end of the function.  This 
   * includes saving parameters and saving registers.  The paramter
   * is the body of the function.
   * <p>
   * Red book, pp. 176 and 271.
   */
  public Tree.Stm procEntryExit1(Tree.Stm body) {
    return body;
  } // procEntryExit1(Tree.Stm) 

  /**
   * Add ``sink'' instructions to the function body to tell the
   * register allocator that certain registers are live at 
   * procedure exit.  Not implemented in the current version.
   */
  public Tree.StmList procEntryExit2(Tree.StmList body) {
    return body;
  } // procEntryExit2(Tree.StmList)

  /**
   * Add more wrapper code to the procedure to allocate space for
   * the frame and stuff.
   * <p>
   * Red book, pp. 176 and 271.
   */ 
  public Tree.StmList procEntryExit3(Tree.StmList body) {
    return body;
  } //  procEntryExit3(Tree.StmList)

} // class IRTFrame
