/// Evolver Copyright 2000, Morgan McGuire
/// matrix@alum.mit.edu   http://graphics3d.com/matrix
/**
 * Some common implementation code for ELExpressions.
 */
public abstract class AbstractELExpression implements ELExpression
{
  /**
   * Returns 1.
   */
  public int numNestedSubexpressions()
  {
    return 1;
  }

  /**
   * Returns this.
   */
  public ELExpression randomNestedSubexpression()
  {
    return this;
  }

  public boolean hasExternalInfluences()
  {
    return false;
  }

  /**
   * returns this.
   */
  public ELExpression getNestedSubexpression(int targetNumber)
  {
    if (targetNumber != 0) {
      throw new Error("Bad search! " + targetNumber);
    }

    return this;
  }

  /**
   * default is only appropriate when cloneWithChildMutations has no
   * children.
   */
  public ELExpression cloneWithReplacement(ELExpression e, int p) 
  {
    return cloneWithChildMutations(null);
  }
   

  /**
   * Returns the genetic clone of one of this expression's siblings.
   * This is convenient to call when implementing geneticClone().
   */
  protected ELExpression cloneSiblingMutation(ELCall parent, GeneticParameters gp)
  {
    if (parent == null) {
      throw new Error("No siblings.");
    }
    
    // We have to clone the expression because copying is occuring.
    // Note that our sibling's parent is our parent.
    return parent.randomChild().geneticClone(parent, gp);
  }

  /**
   * Returns a clone of this expression with the children genetically
   * cloned, surrounded by another randomly generated expression.  It
   * may be convenient to call this when implementing geneticClone().
   */
  protected ELExpression encloseInNewCallMutation(GeneticParameters gp)
  {
    return gp.randomCallWithOperator(cloneWithChildMutations(gp));
  }

  /**
   * Clone, genetically cloning children but perfectly cloning this 
   * expression itself.  The default implementation of
   * encloseInNewCallMutation calls this method.
   */
  protected ELExpression cloneWithChildMutations(GeneticParameters gp)
  {
    return (ELExpression)clone();
  }

  public boolean sameExpression(ELExpression other)
  {
    return this.unparse().equals(other.unparse());
  }

  abstract public Object clone();
}
