/**
 * The building block of Scheme lists.
 *
 * @author Samuel A. Rebelsky
 * @author Yvonne Palm
 * @author "I was here before Sam" Leach
 * @author Jonathan "Back in class" Wellons
 */
public class ConsCell
  implements SchemeList
{
  // +-----------+-----------------------------------------------
  // | Constants |
  // +-----------+

  // +--------+--------------------------------------------------
  // | Fields |
  // +--------+

  /** 
   * The car (the first element in the list).
   */
  Object myCar;

  /**
   * The cdr of this list.
   */
  ConsCell myCdr;


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

  /**
   * Build a new list with car newCar and cdr newCdr.
   */
  public ConsCell(Object newCar, ConsCell newCdr)
  {
    this.myCar = newCar;
    this.myCdr = newCdr;
  } // ConsCell(Object, ConsCell)


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

  /** 
   * Determine if this list is empty.
   */
  public boolean isEmpty()
  {
    return false;
  } // isEmpty()

  /**
   * Create a new list by adding something to the front of this list.
   */
  public SchemeList addToFront(Object val)
  {
    return new ConsCell(val, this);
  } // addToFront(Object)
  
  /**
   * Get the initial element of the list.
   */
  public Object car()
    throws EmptyListException
  {
    return this.myCar;
  } // car()

  /**
   * Get a list that contains all but the first element.
   */
  public SchemeList cdr()
    throws EmptyListException
  {
    return this.myCdr;
  } // cdr()

  /**
   * Convert this list to a string (often for printing).
   */
  public String toString() 
  {
    String result = "(" + this.myCar;
    SchemeList remainder = this.myCdr;
    // The following code is in a try-catch block because Java is
    // overly anal.  We know that car and cdr can't fail b/c we
    // check emptiness first, but Java can't tell the relationship.
    try {
      while (!remainder.isEmpty()) {
        result = result + " " + remainder.car();
        remainder = remainder.cdr();
      }
    }
    catch (Exception e) {
    }
    return result + ")";
  } // toString()
} // class ConsCell
