/// Evolver Copyright 2000, Morgan McGuire
/// matrix@alum.mit.edu   http://graphics3d.com/matrix
/**
 * A symbolic expression in the EL language.  An expression "contains"
 * all of its subexpressions.  An expression can appear in exactly one
 * other expression; they are never shared between expressions.
 * 
 * An expression cannot be mutated (to allow future expansion to
 * expression sharing).
 *
 *<PRE>
 *
 * ELExpression := ELCall | ELScalar | ELVector
 * ELCall := (ELOperator ELExpression*)
 *
 *</PRE> */
public interface ELExpression extends Cloneable
{
  /**
   * The total number of nodes (including this one) below this expression.
   * For example: Noise() -> 1, Add(X(), Y()) -> 3.
   */
  public int numNestedSubexpressions();

  /**
   * Clones, possibly mutating.  The operators will be shared between
   * clones but no ELExpressions will be shared.
   *
   * @param parent Parent expression from previous generation.  don't
   * point at or mutate this; it is provided so you can get access to
   * siblings.  May be null if there is no parent (i.e. top-level
   * expression).
   */
  public ELExpression geneticClone(ELCall parent, GeneticParameters gp);

  /**
   * Returns true if the output is influenced by the environment.
   */
  public boolean hasExternalInfluences();

  /**
   * Creates a perfect clone with expression substitited for node at
   * position.
   * @param expression Is not cloned.
   */
  public ELExpression cloneWithReplacement(ELExpression expression, int position);

  /**
   * Chooses a nested subexpression of this expression (possibly the
   * expression itself) and returns a pointer to it (not a clone)
   */
  public ELExpression randomNestedSubexpression();

  public ELExpression getNestedSubexpression(int targetNumber);

  /**
   * Generates an EL language source string sufficient to uniquely
   * identify this expression.
   */
  public String unparse();

  /**
   * Return true if this and other are equivalent expressions (unparse
   * to the same value).
   */
  // DESIGN NOTE: Intentionally does not override equals(), which changes the
  // behavior of hash table and requires overriding hashCode() as
  // well.
  public boolean sameExpression(ELExpression other);

  /**
   * Evaluates this expression.
   * @param out Destination of result.
   * @param environment Global environment
   * @param pl Local environment (function arguments).  May be null.  These
   * are usually passed from parent to child expression.
   */
  public void evaluate(ELMatrix out, ELEnvironment environment, ParameterList pl);
  
  public Object clone();
}
