/**
   * Returns an unevaluated term node if any. If none exists, <code>null<code> is returned
   *
   * @return <code>Node</code> representing a term node that has not been evaluated. If no such child exists, null is returned.
   */
  public ASTNode getUnevaluatedTerm() {

    // get first child
    ASTNode child = this.getFirst();

    // while the current child exists and has been evaluated, cycle to the next child
    while (child != null && child.isEvaluated()) {
      child = child.getNext();
    }

    // null will be returned when no children are left unevaluated, otherwise and unevaluated
    // child node will be returned.
    return child;
  }
  /* (non-Javadoc)
   * @see org.coreasm.engine.Plugin#interpret(org.coreasm.engine.interpreter.Node)
   */
  public ASTNode interpret(Interpreter interpreter, ASTNode pos) {

    ASTNode nextPos = pos;
    String x = pos.getToken();
    String gClass = pos.getGrammarClass();

    // if number related expression
    if (gClass.equals(ASTNode.EXPRESSION_CLASS)) {
      // it is a number constant
      if (x != null) {

        // get new string element representing lexeme from string background
        StringElement se = stringBackgroundElement.getNewValue(x);

        // result of this node is the string element produced
        pos.setNode(null, null, se);
      }
    }

    return nextPos;
  }
  public Element interpretOperatorNode(Interpreter interpreter, ASTNode opNode)
      throws InterpreterException {
    Element result = null;
    String x = opNode.getToken();
    String gClass = opNode.getGrammarClass();

    // if class of operator is binary
    if (gClass.equals(ASTNode.BINARY_OPERATOR_CLASS)) {

      // get operand nodes
      ASTNode alpha = opNode.getFirst();
      ASTNode beta = alpha.getNext();

      // get operand values
      Element l = alpha.getValue();
      Element r = beta.getValue();

      // if both operands are undef, the result is undef
      if (l.equals(Element.UNDEF) && r.equals(Element.UNDEF)) {
        capi.warning(
            PLUGIN_NAME,
            "Both operands of the '" + x + "' operator were undef.",
            opNode,
            interpreter);
        result = Element.UNDEF;
      } else
      // confirm that at least one of the operands is a string elements, otherwise throw an error
      if ((l instanceof StringElement || r instanceof StringElement)) {
        if (x.equals(STRINGCONCAT_OP))
          result = stringBackgroundElement.getNewValue(l.toString() + r);
      }
      // otherwise
      //    throw new InterpreterException("At least one operand must be strings for '"+x+"'
      // operation.");
    }

    return result;
  }
  @Override
  public void compile(CodeFragment result, ASTNode node, CompilerEngine engine)
      throws CompilerException {
    System.out.println("called, father is " + node.getParent());
    try {
      LetRuleNode letrule = (LetRuleNode) node;
      Map<String, ASTNode> letmap = letrule.getVariableMap();

      result.appendLine("//start of let\n");
      result.appendLine("localStack.pushLayer();\n");
      for (Entry<String, ASTNode> entry : letmap.entrySet()) {
        CodeFragment val = engine.compile(entry.getValue(), CodeType.R);
        result.appendFragment(val);
        result.appendLine("localStack.put(\"" + entry.getKey() + "\", evalStack.pop());\n");
      }

      result.appendFragment(engine.compile(letrule.getInRule(), CodeType.U));
      result.appendLine("localStack.popLayer();\n");
      result.appendLine("//end of let\n");
    } catch (Exception e) {
      throw new CompilerException(e);
    }
  }