/**
   * Set the type of the given node to be the return type of the method determined for the given
   * node.
   *
   * @param node The specified node.
   * @exception IllegalActionException If an inference error occurs.
   */
  public void visitMethodCallNode(ASTPtMethodCallNode node) throws IllegalActionException {
    Type[] childTypes = _inferAllChildren(node);

    // Handle indexing into a record.
    if ((childTypes.length == 1) && childTypes[0] instanceof RecordType) {
      RecordType type = (RecordType) childTypes[0];

      if (type.labelSet().contains(node.getMethodName())) {
        _setType(node, type.get(node.getMethodName()));
        return;
      }
    }

    CachedMethod cachedMethod =
        CachedMethod.findMethod(node.getMethodName(), childTypes, CachedMethod.METHOD);

    if (cachedMethod.isValid()) {
      Type type = cachedMethod.getReturnType();
      _setType(node, type);
    } else {
      // If we reach this point it means the function was not found on
      // the search path.
      StringBuffer buffer = new StringBuffer();

      for (int i = 1; i < childTypes.length; i++) {
        if (i == 1) {
          buffer.append(childTypes[i].toString());
        } else {
          buffer.append(", " + childTypes[i].toString());
        }
      }

      throw new IllegalActionException(
          "No matching method "
              + childTypes[0].toString()
              + "."
              + node.getMethodName()
              + "( "
              + buffer
              + " ).");
    }
  }