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

package IR2;

import java.util.*;

public class Program extends SymbolTable implements Walkable {
  private int data_area_offset;

  public Program() { super(null); }


  /* This procedure generates delocalized code streams for each method. */
  public void generate_delocalized_code(Codegen c) {
    Enumeration e = elements();
    while (e.hasMoreElements()) {
      Descriptor d = (Descriptor) e.nextElement();

      if (d instanceof MethodDescriptor)
        ((MethodDescriptor) d).generate_delocalized_code(c);
    }
  }


  /* Procedure for allocating locations for global variables and for
   * allocating locations in stack frames (by calling
   * MethodDescriptor.allocate_locations() on methods). */
  public void allocate_locations(Codegen c) {
    data_area_offset = 0;
    Enumeration e = elements();
    while (e.hasMoreElements()) {
      Descriptor d = (Descriptor) e.nextElement();
      /* I think instanceof is probably OK here because I'm using it
       * to sift out the method descriptors. */
      if (d instanceof GlobalScalarVarDescriptor) {
        data_area_offset =
          ((GlobalScalarVarDescriptor) d).set_offset(data_area_offset);
      } else if (d instanceof ArrayVarDescriptor) {
        data_area_offset =
          (       (ArrayVarDescriptor) d).set_offset(data_area_offset);
      } else if (d instanceof MethodDescriptor) {
        ((MethodDescriptor) d).allocate_locations(c);
      }

      if (data_area_offset < 0) {
        /* Data area overflow: there's over 2 gigawords!  This can't
         * happen in a valid Decaf program.  Ignore.  */
      }
    }
  }

  // Hey, optimize! 
  public void perform_optimizations(boolean cp, boolean dce) {
    Enumeration e = elements();
    while (e.hasMoreElements()) {
      Descriptor d = (Descriptor) e.nextElement();

      if (d instanceof MethodDescriptor)
        ((MethodDescriptor) d).optimize(cp, dce);
    }
  }

  /* This procedure generates the final code stream. */
  public void generate_cooked_code(Codegen c) {
    c.reserve_zeroed_data_area(data_area_offset);

    Enumeration e = elements();
    while (e.hasMoreElements()) {
      Descriptor d = (Descriptor) e.nextElement();

      if (d instanceof MethodDescriptor)
        ((MethodDescriptor) d).generate_cooked_code(c);
    }
  }

  /* Walkable methods. */
  public String node_name() { return "Program"; }
}
